Keep your place in this quest

Log in or sign up for free to subscribe, follow lesson progress, and access more learning content.

Пример: Полная игра

Этот урок создаёт небольшую коллекционную игру. Игрок перемещается по сцене, сталкивается со стенами, собирает монеты и выводит итоговый счёт, когда игра заканчивается.

Вместо того чтобы вставлять весь скрипт сразу, пример разбит на те же части, которые вы будете использовать в большинстве проектов Tiniest2D:

  • переменные ассетов и состояния
  • start()
  • onUpdate(dt)
  • onCollision(objA, objB)
  • end()

1. Ассеты и состояние игры

Первый раздел создаёт ассеты и переменные, которые будут использоваться в остальной части скрипта. Спрайты — это изображения, сцена — это уровень, игрок — это объект, размещённый в этой сцене, а переменные счёта/скорости хранят простое состояние игры.

// Создать ассеты
var playerImg = Sprite(16, 16)
var wallImg = Sprite(16, 16)
var coinImg = Sprite(8, 8)
var level = Scene()

// Создать игрока
var player = Object("Player")

// Состояние игры
var score = 0
var speed = 100

На этом этапе переменные существуют, но игра ещё не поместила ничего в сцену. Эта настройка происходит в start().

2. Функция start()

start() запускается один раз, когда начинается игра. Используйте её для настройки объектов, установки первой сцены, позиционирования камеры и подготовки начальных значений.

func start() {
    // Настройка игрока
    setSprite(player, playerImg)
    setCollisionType(player, COLLISION_DYNAMIC())
    setX(player, 50)
    setY(player, 50)
    addObject(level, player)

    // Установить начальную сцену
    setScene(level)

    // Центрировать камеру на игроке
    setCameraX(level, getX(player))
    setCameraY(level, getY(player))
    setCameraZoom(level, 3)

    print("Соберите монеты!")
}

Игрок использует COLLISION_DYNAMIC(), потому что он должен сталкиваться и быть вытолкнутым из стен. Камера начинает с центровки на игроке, чтобы вид уровня начинался в правильном месте.

3. Функция onUpdate(dt)

onUpdate(dt) выполняется каждый кадр. Здесь игрок читает ввод, перемещается, обновляет камеру и проверяет клавиши сброса.

dt означает "дельта время": количество времени с предыдущего кадра. Умножение движения на dt делает скорость движения более последовательной на разных частотах кадров.

func onUpdate(dt) {
    // Движение игрока
    var moveX = 0
    var moveY = 0

    if (isKeyHeld(KEY_LEFT()) || isKeyHeld(KEY_A())) {
        moveX = -1
    }
    if (isKeyHeld(KEY_RIGHT()) || isKeyHeld(KEY_D())) {
        moveX = 1
    }
    if (isKeyHeld(KEY_UP()) || isKeyHeld(KEY_W())) {
        moveY = -1
    }
    if (isKeyHeld(KEY_DOWN()) || isKeyHeld(KEY_S())) {
        moveY = 1
    }

    // Применить движение
    setX(player, getX(player) + moveX * speed * dt)
    setY(player, getY(player) + moveY * speed * dt)

    // Камера следует за игроком
    setCameraX(level, getX(player))
    setCameraY(level, getY(player))

    // Сброс уровня с помощью клавиши R
    if (isKeyPressed(KEY_R())) {
        resetScene(level)
        setX(player, 50)
        setY(player, 50)
        score = 0
        print("Уровень сброшен!")
    }
}

Код движения формирует направление на основе ввода с клавиатуры. Затем он добавляет это направление к текущей позиции игрока. Камера обновляется после движения, чтобы следовать за новой позицией.

4. Функция onCollision(objA, objB)

onCollision(objA, objB) выполняется, когда два объекта сталкиваются. В этом примере монеты должны использовать COLLISION_TRIGGER(). Триггерные объекты сообщают о перекрытиях, но не блокируют движение.

func onCollision(objA, objB) {
    var nameB = getName(objB)
    var typeB = getCollisionType(objB)

    // Сбор монет (монеты должны быть типа TRIGGER в редакторе сцены)
    if (typeB == COLLISION_TRIGGER()) {
        removeObject(level, objB)
        score = score + 1
        print("Счёт: " + score)
    }
}

Когда игрок касается триггера, скрипт удаляет этот объект из сцены и увеличивает счёт. Это основной шаблон для получения предметов, ключей, усилителей и контрольных точек.

5. Функция end()

end() запускается, когда игра останавливается. В этом примере просто выводится итоговый счёт, но в более крупных играх можно использовать эту функцию для очистки или финальных отладочных сообщений.

func end() {
    print("Итоговый счёт: " + score)
}

Настройка примера

  1. Создайте спрайты:
  2. Ctrl+Клик на playerImg, нарисуйте персонажа (например, простую фигуру)
  3. Ctrl+Клик на wallImg, нарисуйте солидный блок
  4. Ctrl+Клик на coinImg, нарисуйте маленький круг или ромб

  5. Дизайн сцены:

  6. Ctrl+Клик на level
  7. Выберите wallImg в левой панели, установите столкновение на "Статическое"
  8. Нарисуйте стены вокруг краёв и создайте лабиринт
  9. Выберите coinImg, установите столкновение на "Нет" для декоративных плиток монет
  10. Разместите монеты по уровню в качестве визуальных подсказок

  11. Создайте триггерные объекты монет:

Спрайты, вставленные в сцену, полезны для плиток и украшений, но собираемые монеты должны быть объектами, чтобы коллизии могли их удалять. Добавьте объекты монет так:

var coin1 = Object("Coin1")
var coin2 = Object("Coin2")

func start() {
    // ... настройка игрока ...

    // Настройка монет как триггеров
    setSprite(coin1, coinImg)
    setCollisionType(coin1, COLLISION_TRIGGER())
    setX(coin1, 100)
    setY(coin1, 80)
    addObject(level, coin1)

    setSprite(coin2, coinImg)
    setCollisionType(coin2, COLLISION_TRIGGER())
    setX(coin2, 150)
    setY(coin2, 120)
    addObject(level, coin2)

    // ... остальная часть start ...
}

Этот же шаблон можно расширить для других монет, врагов, дверей или любых объектов, которым необходимо поведение скрипта.