Занятие 11
Это надо знать
На прошлом занятии мы рассмотрели движение одного шарика (героя) по траектории. Рассмотрим случай, когда на экране два шарика.Для первого шарика начальные значения будут следующими:
double x1 = 100, double y1 = 100;
double vx1 = 5, double vy1 = 7;
Для второго шарика начальные значения будут следующими:
double x2 = 300, double y2 = 200;
double vx2 = 4, double vy2 = 3;
Нарисуем синий и красный шарики:
txSetFillColor (TX_RED);
txCircle (x1, y1, 15);
txSetFillColor (TX_BLUE);
txCircle (x2, y2, 15);
Функция MoveBall будет содержать команды для движения шарика с координатами (x1, y1) и команды для движения шарика с координатами (x2, y2).
x1 = x1 + vx1*dt; // изменение координат первого шарика
y1 = y1 + vy1*dt;
x2 = x2 + vx2*dt; // изменение координат второго шарика
y2 = y2 + vy2*dt;
if (x1 > 600 - 15) // проверка столкновения со стенами первого шарика
{
vx1 = -vx1;
x1 = 600 - 15;
}
if (x1 < 0 + 15)
{
vx1 = -vx1;
x1 = 0 + 15;
}
if (y1 < 0 + 15)
{
vy1 = -vy1;
y1 = 0 + 15;
}
if (y1 > 400 - 15)
{
vy1 = -vy1;
y1 = 400 - 15;
}
if (x2 > 600 - 15) // проверка столкновения со стенами второго шарика
{
vx2 = -vx2;
x2 = 600 - 15;
}
if (x2 < 0 + 15)
{
vx2 = -vx2;
x2 = 0 + 15;
}
if (y2 < 0 + 15)
{
vy2 = -vy2;
y2 = 0 + 15;
}
if (y2 > 400 - 15)
{
vy2 = -vy2;
y2 = 400 - 15;
}
Создадим две функции:
Рисование шарика: DrawBall:
Движение шарика: Physics.
Вызов функции DrawBall:
DrawBall (x1, y1, TX_RED);
DrawBall (x2, y2, TX_BLUE);
Функция DrawBall:
void DrawBall (double x, double y, COLORREF color)
{
txSetFillColor (color);
txCircle (x, y, 15);
}
Вызов функции Physics.:
Physics (x1, y1, vx1, vy1, dt);
Physics (x2, y2, vx2, vy2, dt);
Функция Physics.:
void Physics (double x, double y, double vx, double vy, double dt)
{
x = x + vx*dt;
y = y + vy*dt;
if (x > 600 - 15)
{
vx = -vx;
x = 600 - 15;
}
if (x < 0 + 15)
{
vx = -vx;
x = 0 + 15;
}
if (y < 0 + 15)
{
vy = -vy;
y = 0 + 15;
}
if (y > 400 - 15)
{
vy = -vy;
y = 400 - 15;
}
}
Запустив программу на выполнение, увидим, что шарики не двигаются, а стоят на месте в первоначальных координатах (100, 100) и (300, 200).
Почему же так произошло? Рассмотрим по шагам работу программы:
1. Присваиваем значения переменным: x1 = 100, y1 = 100, vx1 = 5, vy1 = 7.
2. Рисуем круг с центром в точке (100, 100) и радиусом 15.
Рисование шарика: DrawBall:
Движение шарика: Physics.
Вызов функции DrawBall:
DrawBall (x1, y1, TX_RED);
DrawBall (x2, y2, TX_BLUE);
Функция DrawBall:
void DrawBall (double x, double y, COLORREF color)
{
txSetFillColor (color);
txCircle (x, y, 15);
}
Вызов функции Physics.:
Physics (x1, y1, vx1, vy1, dt);
Physics (x2, y2, vx2, vy2, dt);
Функция Physics.:
void Physics (double x, double y, double vx, double vy, double dt)
{
x = x + vx*dt;
y = y + vy*dt;
if (x > 600 - 15)
{
vx = -vx;
x = 600 - 15;
}
if (x < 0 + 15)
{
vx = -vx;
x = 0 + 15;
}
if (y < 0 + 15)
{
vy = -vy;
y = 0 + 15;
}
if (y > 400 - 15)
{
vy = -vy;
y = 400 - 15;
}
}
Запустив программу на выполнение, увидим, что шарики не двигаются, а стоят на месте в первоначальных координатах (100, 100) и (300, 200).
Почему же так произошло? Рассмотрим по шагам работу программы:
1. Присваиваем значения переменным: x1 = 100, y1 = 100, vx1 = 5, vy1 = 7.
2. Рисуем круг с центром в точке (100, 100) и радиусом 15.
3. Вызываем функцию Physics, передаем значения параметров: х = 100, у = 100, vx = 5, vy = 7, dt = 1.
4. Функция Physics изменяет значения х = 100 + 5*1 = 105 и у = 100 + 7*1 = 107.
5. Возвращаемся в функцию MoveBall, и функция Physics не передала нам новые значения х1 и у1, следовательно, они не меняются, и x1 = 100, y1 = 100. Шарик стоит на месте.
Указатели
Указатель - специальный тип переменной, который может хранить адрес значения.
Когда мы передаем в функцию Physics значения х1 и у1, функция работает с копиями этих переменных, следовательно, надо изменять не копии, а функция должна знать, где находятся оригиналы переменных и изменять их. Т.е. функция Physics должна принимать не копию переменной х1, а адрес (указатель) того места, где хранится оригинал х1.
В языке Си есть оператор & (амперсант), который записывается перед именем переменной, и такая запись будет означать адрес этой переменной.
Т.к. функция Physics изменяет значения переменных х1, у1, vx1, vу1 для первого шарика и х2, у2, vx2, vу2 для второго шарика, будем передавать их адреса:
Physics (&x1, &y1, &vx1, &vy1, dt);
Physics (&x2, &y2, &vx2, &vy2, dt);
В самой функции Physics теперь надо указать, что х, у, vx, vу - это не числа, а адреса чисел.
Запись double* x означает, что х - адрес некоторого числа.
void Physics (double* x, double* y, double* vx, double* vy, double dt)
Все строчки, которые содержали переменные х, у, vx, vу, теперь будут работать с адресами этих переменных, поэтому заменим и их на *х, *у, *vx, *vу:
{
*x = *x + *vx*dt;
*y = *y + *vy*dt;
if (*x > 600 - 15)
{
*vx = - *vx;
*x = 600 - 15;
}
if (*x < 0 + 15)
{
*vx = - *vx;
*x = 0 + 15;
}
if (*y < 0 + 15)
{
*vy = - *vy;
*y = 0 + 15;
}
if (*y > 400 - 15)
{
*vy = - *vy;
*y = 400 - 15;
}
}
Т.к. теперь происходит изменение переменных х1, у1, vx1, vу1 и х2, у2, vx2, vу2, оба шарика будут двигаться.
Указатель - специальный тип переменной, который может хранить адрес значения.
Когда мы передаем в функцию Physics значения х1 и у1, функция работает с копиями этих переменных, следовательно, надо изменять не копии, а функция должна знать, где находятся оригиналы переменных и изменять их. Т.е. функция Physics должна принимать не копию переменной х1, а адрес (указатель) того места, где хранится оригинал х1.
В языке Си есть оператор & (амперсант), который записывается перед именем переменной, и такая запись будет означать адрес этой переменной.
Т.к. функция Physics изменяет значения переменных х1, у1, vx1, vу1 для первого шарика и х2, у2, vx2, vу2 для второго шарика, будем передавать их адреса:
Physics (&x1, &y1, &vx1, &vy1, dt);
Physics (&x2, &y2, &vx2, &vy2, dt);
В самой функции Physics теперь надо указать, что х, у, vx, vу - это не числа, а адреса чисел.
Запись double* x означает, что х - адрес некоторого числа.
void Physics (double* x, double* y, double* vx, double* vy, double dt)
Все строчки, которые содержали переменные х, у, vx, vу, теперь будут работать с адресами этих переменных, поэтому заменим и их на *х, *у, *vx, *vу:
{
*x = *x + *vx*dt;
*y = *y + *vy*dt;
if (*x > 600 - 15)
{
*vx = - *vx;
*x = 600 - 15;
}
if (*x < 0 + 15)
{
*vx = - *vx;
*x = 0 + 15;
}
if (*y < 0 + 15)
{
*vy = - *vy;
*y = 0 + 15;
}
if (*y > 400 - 15)
{
*vy = - *vy;
*y = 400 - 15;
}
}
Т.к. теперь происходит изменение переменных х1, у1, vx1, vу1 и х2, у2, vx2, vу2, оба шарика будут двигаться.
Пример
Создадим движение нескольких героев по траектории.Посмотреть текст программы
Результат работы программы