Переменные в Dart можно объявить с помощью ключевого слова var
.
var hello = 'Привет';
Переменная - название для кусочка памяти с какими-либо данными. Обычно пишутся в lowerCamelCase.
Одним из отличительных качеств переменных является то, что в течение работы программы мы можем сколько угодно менять их значение. Если же значение переменной менять не нужно, а иногда даже нежелательно, то вместо переменных можно использовать константы. Константы определяются с помощью ключевых слов const
и final
(отличие между ними в том, что значение final-переменной определяется во время выполнения программы, а const - при сборке и запуске):
void main (){
const name = "Артём";
print(name);
name = "Михаил";
}
На 4 строчке произойдет ошибка при повторном присвоении имени const-переменной.
В Dart есть несколько базовых (примитивных) типов, которые используются для хранения простых значений. Вот основные из них:
String greet = "Привет!";
print(greet); // А ещё можно оставлять комментарии в коде вот такие
/* И
вот
такие */
int age = 16;
int year = 2025;
print('Мой возраст: $age, год: $year');
double temperature = 36.6;
double height = 1.75;
print('Температура: $temperature, рост: $height');
bool isLightOn = true;
bool isDoorClosed = false;
print('Свет включен? $isLightOn');
print('Дверь закрыта? $isDoorClosed');
В Dart условные конструкции if и else используются для того, чтобы программа выполняла разные действия в зависимости от условий.
Как это работает:
Если условие в круглых скобках после if истинно (true), то выполняется блок кода внутри фигурных скобок после if.
Если условие ложно (false) и указана конструкция else, то выполняется блок кода внутри фигурных скобок после else.
int number = 15;
if (number > 10) {
print("Число больше 10");
} else {
print("Число меньше или равно 10");
}
int score = 78;
if (score >= 90) {
print("Отлично");
} else if (score >= 78) {
print("Хорошо");
} else {
print("Удовлетворительно");
}
Циклы for в Dart нужны для того, чтобы повторять один и тот же кусочек кода несколько раз. Можно их использовать, когда заранее известно, сколько раз нужно выполнить повторение.
Как это работает:
Внутри круглых скобок после for указывают три части, разделенные точкой с запятой:
Инициализация: объявляется счетчик, например, int i = 0.
Условие: проверка, когда нужно продолжать цикл, например, i < 5.
Изменение счетчика: действие, которое выполняется после каждого прохода, например, i++ (уменьшает или увеличивает значение счетчика, эквивалентно i = i+1).
Если условие истинно, выполняется блок кода внутри фигурных скобок. После выполнения кода происходит увеличение (или иное изменение) счетчика, и условие проверяется снова.
void main() {
for (int i = 0; i < 5; i++) {
print('Этап $i');
}
}
В Dart функции — это блоки кода, которые можно вызвать, чтобы выполнить повторяющуюся задачу. Функции помогают сократить дублирование кода и сделать программу более понятной.
Основные моменты:
Определение функции:
Функция объявляется с указанием возвращаемого типа (например, int, void, String), имени и списка параметров в круглых скобках.
Параметры и аргументы:
Функция может принимать параметры (данные, которые передаются в функцию) и возвращать результат через оператор return. Если функция не возвращает значение, используется тип void.
Вызов функции:
Чтобы использовать функцию, вызывается её имя с нужными аргументами в круглых скобках.
Лямбда-выражения (arrow functions):
Если функция содержит одно выражение, можно воспользоваться сокращенной записью с оператором =>.
Параметры с значением по умолчанию:
Можно задать значение по умолчанию для параметров, если аргумент не передается.
// Функция, которая складывает два числа и возвращает результат
int add(int a, int b) {
return a + b;
}
// Функция, которая выводит приветствие. У неё нет возвращаемого значения (void).
void sayHello(String name) {
print("Привет, $name!");
}
// Функция, записанная с помощью оператора => (однострочная функция)
int multiply(int a, int b) => a * b;
// Функция с параметром по умолчанию
String sayHelloByName([String name = "Незнакомец"]) {
return "Привет, $name!";
}
void main() {
// Вызов функции add
int sum = add(3, 4);
print("Сумма: $sum");
// Вызов функции sayHello
sayHello("Артём");
// Вызов функции multiply
int product = multiply(5, 6);
print("Произведение: $product");
// Вызов функции sayHello с и без параметра
print(sayHelloByName("Артём"));
print(sayHelloByName());
}
В Dart существуют разные структуры данных, которые помогают хранить и управлять информацией. Вот основные из них:
void main() {
List<String> fruits = ['Яблоко', 'Банан', 'Апельсин'];
print(fruits[0]); // Выведет: Яблоко
// Добавление элемента в список
fruits.add('Груша');
print(fruits);
}
void main() {
Map<String, int> ages = {
'Артём': 21,
'Михаил': 24,
};
print(ages['Артём']); // Выведет: 20
// Добавление новой пары
ages['Иван'] = 29;
print(ages);
}
Класс в Dart — это как чертёж, по которому можно создавать объекты. Объект — это экземпляр класса, содержащий данные (свойства) и поведение (методы). Классы помогают структурировать код и объединять данные и функции, которые работают с этими данными.
Основные моменты:
Ключевое слово class
используется для объявления класса.
Свойства (поля) класса хранят данные.
Методы — это функции внутри класса, описывающие поведение.
Конструктор — специальный метод, который вызывается при создании нового объекта.
class Person {
String name;
int age;
// Конструктор для создания нового объекта Person
Person(this.name, this.age);
// Метод, который выводит приветствие
void sayHello() {
print("Привет, меня зовут $name, и мне $age лет.");
}
}
void main() {
// Создаем объект типа Person
Person person = Person("Артём", 21);
person.sayHello(); // Вывод: Привет, меня зовут Артём, и мне 21 лет.
}
Асинхронные функции позволяют выполнять задачи, которые не завершатся мгновенно (например, загрузку данных из интернета), не останавливая выполнение остальной части программы. Главное здесь — тип Future, который обещает вернуть результат позже.
Что такое асинхронные функции:
Функция с ключевым словом async возвращает Future.
Ключевое слово await используется, чтобы дождаться завершения асинхронной операции.
Такие функции позволяют писать код, как будто он синхронный, упрощая чтение и поддержку.
void main() async {
print("Начало загрузки данных...");
String data = await fetchData(); // ждем результат выполнения fetchData()
print("Полученные данные: $data");
print("Загрузка завершена!");
}
Future<String> fetchData() async {
// Симулируем задержку в 2 секунды, как если бы данные загружались из сети
await Future.delayed(Duration(seconds: 2));
return "Данные успешно загружены!";
}
Объяснение:
В функции main используется async, что означает, что внутри можно применять await.
При вызове await fetchData() выполнение main приостанавливается, пока fetchData не завершится.
fetchData() симулирует задержку с помощью Future.delayed и возвращает строку.
После получения результата выполнение продолжается.
Если мы уберём await, код в main не будет приостанавливаться и это может привести к ошибкам. Например, если убрать await перед Future.delayed, код не будет ожидать завершения двухсекундного события, и сразу всё выведет на экран.
Flame — это мощный и модульный 2D игровой движок для Flutter. Он создан, чтобы упростить и ускорить разработку игр для широкого круга платформ, используя всю мощь и гибкость фреймворка Flutter.
https://examples.flame-engine.org/
https://bonfire-engine.github.io/examples/bonfire-v3/
main
функцияvoid main() {
runApp(GameWidget(game: SpaceShooterGame()));
}
runApp
: Запускает Flutter-приложение.
GameWidget
: Обертка для игры, которая позволяет встроить её в Flutter.
Принимает объект игры (в данном случае SpaceShooterGame
).
Управляет отрисовкой и обновлением игры.
SpaceShooterGame
class SpaceShooterGame extends FlameGame with PanDetector {
late Player player;
@override
Future<void> onLoad() async {
player = Player();
add(player);
}
@override
void onPanUpdate(DragUpdateInfo info) {
player.move(info.delta.global);
}
}
FlameGame
: Базовый класс для создания игр.
Управляет игровым циклом (update
, render
).
Содержит список компонентов (children
), которые обновляются и отрисовываются.
PanDetector
: Миксин для обработки жестов (например, свайпов и перетаскиваний).
onPanUpdate
: Вызывается при перемещении пальца по экрану.
info.delta.global
: Вектор перемещения пальца.Player
class Player extends PositionComponent with HasGameReference<SpaceShooterGame> {
Player() : super(size: Vector2(100, 150), anchor: Anchor.center);
static final _paint = Paint()..color = Colors.white;
@override
void render(Canvas canvas) {
canvas.drawRect(size.toRect(), _paint);
}
@override
Future<void> onLoad() async {
await super.onLoad();
position = game.size / 2;
anchor = Anchor.center;
}
void move(Vector2 delta) {
position.add(delta);
}
}
PositionComponent
: Базовый класс для объектов с позицией и размером.
size
: Размер объекта (Vector2(width, height)
).
position
: Позиция объекта на экране (Vector2(x, y)
).
anchor
: Точка привязки объекта (по умолчанию Anchor.topLeft
).
HasGameReference
: Миксин для доступа к объекту игры (game
).
render
: Метод для отрисовки объекта.
Canvas
для рисования прямоугольника.onLoad
: Метод, вызываемый при добавлении объекта в игру.
move
: Метод для перемещения игрока.
position.add(delta)
: Добавляет вектор перемещения к текущей позиции.GameWidget
Параметры:
loadingBuilder
: Показывает загрузочный экран, пока игра инициализируется.
overlayBuilderMap
: Создает оверлеи (например, меню паузы).
backgroundBuilder
: Устанавливает фон для игры.
Пример:
GameWidget(
game: SpaceShooterGame(),
loadingBuilder: (context) => Center(child: Text("Загрузка...")),
overlayBuilderMap: {
'pauseMenu': (context, game) => Center(child: Text("Пауза")),
},
);
FlameGame
Методы:
update(double dt)
: Вызывается каждый кадр для обновления логики игры.
dt
: Время, прошедшее с последнего кадра.onMount()
: Вызывается, когда игра добавляется в GameWidget
.
onRemove()
: Вызывается, когда игра удаляется.
add(Component component)
: Добавляет компонент в игру.
remove(Component component)
: Удаляет компонент из игры.
Пример:
@override
void update(double dt) {
super.update(dt);
// Логика игры (например, спавн врагов).
}
PositionComponent
Методы:
setByRect(Rect rect)
: Устанавливает позицию и размер через Rect
.
angle
: Угол поворота компонента (в радианах).
scale
: Масштаб компонента (Vector2
).
children
: Список дочерних компонентов.
Пример:
@override
void onLoad() async {
angle = 45 * (pi / 180); // Поворот на 45 градусов.
scale = Vector2(2, 2); // Увеличение в 2 раза.
}
PanDetector
Методы:
onPanStart(DragStartInfo info)
: Вызывается при начале жеста.
onPanEnd(DragEndInfo info)
: Вызывается при завершении жеста.
onPanCancel()
: Вызывается при отмене жеста.
Пример:
@override
void onPanStart(DragStartInfo info) {
print("Жест начался: ${info.globalPosition}");
}
update
, render
, PanDetector
и HasGameReference
update
Метод update
— это часть игрового цикла, которая отвечает за обновление состояния игры. Он вызывается каждый кадр (обычно 60 раз в секунду) и используется для:
Обновления позиций объектов.
Проверки коллизий.
Обработки логики игры (например, спавн врагов, подсчет очков).
Параметр double dt
:
Это время, прошедшее с последнего вызова update
. Оно измеряется в секундах.
Используется для плавного движения объектов независимо от частоты кадров.
Пример: position.x += speed * dt;
Пример использования:
@override
void update(double dt) {
super.update(dt); // Важно вызывать super.update!
// Двигаем врага влево.
enemy.position.x -= enemySpeed * dt;
// Проверяем, вышел ли враг за пределы экрана.
if (enemy.position.x < 0) {
enemy.removeFromParent(); // Удаляем врага.
}
}
Для любой логики, которая должна обновляться каждый кадр:
Движение объектов.
Анимации.
Обработка ввода (например, клавиатура, жесты).
render
Метод render
отвечает за отрисовку объектов на экране. Он вызывается каждый кадр после update
.
Параметр Canvas canvas
:
Это объект, на котором рисуются все элементы игры.
Используется для рисования фигур, текста, изображений.
Пример: canvas.drawRect(size.toRect(), paint);
Пример использования:
@override
void render(Canvas canvas) {
super.render(canvas); // Важно вызывать super.render!
// Рисуем прямоугольник.
canvas.drawRect(
Rect.fromLTWH(position.x, position.y, size.x, size.y),
Paint()..color = Colors.blue,
);
}
Для отрисовки кастомных объектов (например, фигур, текста).
Если стандартные компоненты (например, SpriteComponent
) не подходят.
PanDetector
PanDetector
— это миксин для обработки жестов на сенсорных устройствах. Он позволяет:
Определять начало, перемещение и завершение жестов.
Обрабатывать свайпы, перетаскивания и другие жесты.
PanDetector
onPanStart(DragStartInfo info)
:
Вызывается, когда пользователь начинает жест (например, касается экрана).
info.globalPosition
: Позиция касания на экране (Vector2
).Пример:
@override
void onPanStart(DragStartInfo info) {
print("Жест начался: ${info.eventPosition}");
}
onPanUpdate(DragUpdateInfo info)
:
Вызывается, когда пользователь перемещает палец по экрану.
info.delta.global
: Вектор перемещения пальца (Vector2
).Пример:
@override
void onPanUpdate(DragUpdateInfo info) {
player.move(info.delta.global);
}
onPanEnd(DragEndInfo info)
:
Вызывается, когда пользователь завершает жест (например, убирает палец).
info.velocity
: Скорость жеста (полезно для "бросания" объектов).Пример:
@override
void onPanEnd(DragEndInfo info) {
print("Жест завершен со скоростью: ${info.velocity}");
}
onPanCancel()
:
Вызывается, если жест был отменен (например, системным событием).
Пример:
@override
void onPanCancel() {
print("Жест отменен.");
}
Для управления объектами с помощью касаний (например, перетаскивание игрока).
Для реализации свайпов (например, в меню).
HasGameReference
HasGameReference
— это миксин, который предоставляет доступ к объекту игры (game
) внутри компонента. Это полезно для:
Получения размеров экрана.
Доступа к другим компонентам игры.
Использования методов игры (например, add
, remove
).
Поле game
:
Это ссылка на объект игры, в котором находится компонент.
game.size
— размер экрана игры.Пример использования:
class Player extends PositionComponent with HasGameReference<SpaceShooterGame> {
@override
Future<void> onLoad() async {
position = game.size / 2; // Устанавливаем позицию в центре экрана.
}
}
Когда компоненту нужно взаимодействовать с игрой (например, добавлять новые объекты).
Когда нужно получить доступ к данным игры (например, размер экрана, настройки).
import 'package:flame/components.dart';
import 'package:flame/events.dart';
import 'package:flame/game.dart';
import 'package:flame/input.dart';
import 'package:flutter/material.dart';
void main() {
runApp(GameWidget(game: SpaceShooterGame()));
}
class SpaceShooterGame extends FlameGame with PanDetector {
late Player player;
@override
Future<void> onLoad() async {
player = Player();
add(player);
}
@override
void onPanUpdate(DragUpdateInfo info) {
player.move(info.delta.global);
}
}
class Player extends PositionComponent with HasGameReference<SpaceShooterGame> {
Player() : super(size: Vector2(100, 150), anchor: Anchor.center);
static final _paint = Paint()..color = Colors.white;
@override
void render(Canvas canvas) {
canvas.drawRect(size.toRect(), _paint);
}
@override
Future<void> onLoad() async {
await super.onLoad();
position = game.size / 2;
anchor = Anchor.center;
}
void move(Vector2 delta) {
position.add(delta);
}
}
Написать функцию, определяющую четность/нечетность числа и выводящую результат в консоль
Написать функцию, которая выводит в консоль произведение всех целых чисел от 1 до 10, используя циклы
Написать класс, в котором есть массив чисел, передающийся через конструктор, а метод sum() возвращает сумму элементов этого массива
Прислать скриншоты DartPad на https://forms.yandex.com/u/67c28684eb61469df8a59744/. На скриншоте обязательно должен быть весь экран - ваш код и его результат выполнения.