Тема: рух об’єктів: використання таймера, рух, моделювання гри мовою C#.
Мета:
Обладнання: комп’ютери зі встановленими ОС, інтегроване середовище програмування MonoDevelop, бібліотек Cairo і Gtk# 3.0.
Структура уроку
Хід уроку
1. Організаційний момент
Вітання з класом. Перевірка присутності і готовності учнів до уроку. Перевірка виконання домашнього завдання.
2. Актуалізація опорних знань
Для створення програмного втілення гри «Гармата» згадаємо вже знайомі класи й методи:
3. Вивчення нового матеріалу
Таймер-планувальник — вбудований засіб мови програмування, що задає виклик певного методу через проміжок часу, вказаний розробником.
Таймер задає багатократне виконання певних дій, дозволяючи, на відміну від циклу, виконувати інші дії у проміжках між зверненнями таймера.
Застосування таймера вже було розглянуто раніше при вивченні елементів подійно-орієнтованого програмування мови C#.
Альтернативний спосіб застосування таймера мовою С# при використанні MonoDevelop такий:
GLib.Timeout.Add(50, new GLib.TimeoutHandler(OnTimeout));
для виклику кожні 50 мс (час може бути іншим) методу OnTimeout (назва може бути іншою). При створенні анімації на області малювання da метод OnTimeout може мати такий вигляд:
bool OnTimeout() { da.QueueDraw(); return true; }
Тут перша вказівка спричиняє виклик методу перемалювання OnDrawn. Її можна замінити на довільні інші вказівки залежно від змісту завдання програми. Див. приклади використання таймера для анімованих зображень: рухомий текст і обертання відрізка. Ці приклади проілюстровано кодами:
при поєднанні з GKT# 2.0 для компіляції вказівкою терміналу:
mcs 0.cs -pkg:mono-cairo -pkg:gtk-sharp-2.0
при поєднанні з GKT# 3.0 для компіляції як консольного проєкту з під'єднанням певних пакунків.
Для перегляду кодів потрібно перейти за посиланням відповідно 2 і 3.
Завантаження зображення з файлу на область малювання подано у прикладі опрацювання пікселів.
4. Інструктаж з ТБ
5. Вироблення практичних навичок
Завдання. Створити комп'ютерну програму мовою С# для гри «Гармата». Мета гри: для даних розташування цілі й початкової швидкості підібрати кут запуску ядра для ураження цілі.
Математична модель. Для зручності програмного втілення систему координат доцільно вибрати таким чином:
Вважати, що рух тіла є рівномірним по горизонталі і зі сталим прискоренням по вертикалі при нехтуванні опором повітря. Інакше кажучи, вважати, що координати центра ядра залежать від часу t таким чином:
x = x0 + v0x · t,
y = y0 + v0y · t + g · t2/2.
Тут:
При виконанні завдання для кроків, що передбачають зміну коду, використати конкурс ідей і порівнювати з очікуваним. Для перегляду здійснювати перехід за гіперпосиланням.
Вказівки до виконання завдання
(на кожному з кроків 1-6 перевірити можливість компіляції та правильність роботи програми, при потребі змінювати код)
Створити консольний застосунок у середовищі MonoDevelop
з налаштуванням підключення пакунків
з таким замовленням пакунків на початку коду
using System; using Cairo; using Gdk; using Gtk;
з такими властивостями класу області малювання бібліотеки Cairo
public int d = 38, // відстань від області малювання до верхньої частини екрану w = 800, // ширина ігрового поля h = 450; // висота ігрового поля public double t = 0, // час dt =0.05,// приріст часу між послі довними викликами таймера x0 = 0, // початкова абсциса зображення ядра y0 =450, // початкова ордината зображення ядра x, // поточна абсциса зображення ядра y, // поточна ордината зображення ядра r = 6, // радіус зображення ядра r_ = 6, // радіус зображення цілі x_ = 720,// абсциса цілі y_ = 383,// ордината цілі v0x = 0, // початкова швидкість ядра по горизонталі v0y = 0, // початкова швидкість ядра по вертикалі g = 9.8; // прискорення земного тяжіння public bool p = false, // чи є потреба перемальовувати? boom = false, // чи влучено у ціль? fault= false; // чи центр чорного круга перетнув нижню або праву межу вікна програми? public ImageSurface surface = new ImageSurface("boom.png"); // зображення вибуху
з таким вікном застосунку.
Порівняти з очікуваним.
У коді класу головного вікна програми описати обробник події натискання кнопки на формі, який зчитує дані з полів введення, переводить градусну міру кута у радіанну, обчислює v0x і v0y і надає властивостям p, boom, fault області малювання відповідних значень true, false, false. Порівняти з очікуваним.
У коді класу області малювання описати метод OnTimeout
для переіодичного виклику й виклик його у класі головного вікна програми кожні 50 мс. Це забезпечує моделюлювання "у режимі реального часу" з мірилом 1 піксель — 1 метр. Порівняти з очікуваним.
У коді методу OnDrawn класу області малювання описати обчислення поточних значень координат центра зображення ядра і властивості fault, відображення ядра й цілі при відсутності контакту між ними. Порівняти з очікуваним.
У коді методу OnDrawn класу області малювання описати імпорт зображення з файлу boom.png поточної теки (де розташовано виконуваний файл) при влученні ядра у ціль і надання змінній boom значення true у цьому випадку. Відображення вибуху здійснювати тоді й лише тоді, коли відстань між центрами зображень ядра й цілі не перевищує суми їхніх радіусів. Центр зображення вибуху бажано розташувати у точці, що поділяє відрізок з кінцями у центрах зображень ядра й цілі у відношенні, оберненій до радіусів зображень, що при дотику збігається з точкою дотику відповідних кіл. Порівняти з очікуваним.
6. Підбиття підсумків уроку
Обговорення проблем виконання завдання. Виставлення оцінок.
7. Домашнє завдання
У разі потреби доробити завдання. Удосконалити проект, передбачивши можливість врахування сили опору повітря, що дорівнює добутку значення деякої сталої γ (передбачити введення її додатного значення з нового поля введення на формі) і швидкості руху ядра, але спрямована протилежно до напрямку цієї швидкості. Використати такі співвідношення:
x = x0 + vx0 · (1 − e − γt ) · γ − 1,
y = y0 + (vy0 · (1 − e − γt ) + gt ) · γ − 1 +
(e − γt − 1) · g · γ − 2.
Ці рівняння можна отримати, розв'язавши систему диференціальних рівнянь:
x' = vx ,
y' = vy ,
(vx)' = − γ · vx ,
(vy)' = − γ · vy + g
з такими початковими значеннями:
x(0) = x0 ,
y(0) = y0 ,
vx(0) = vx0 ,
vy(0) = vy0 .
Теорію диференціальних рівнянь вивчають у вищій школі, тому виведення рівнянь тут не подано.
Текст упорядкував Олександр Рудик.