Разработка игр с использованием Go и библиотеки Ebiten

от автора

Go является мощным и эффективным языком программирования, который можно использовать для создания игр. В этой статье мы рассмотрим разработку простой игры с использованием языка Go и библиотеки Ebiten, предназначенной для создания 2D игр.

Что такое Ebiten?

Ebiten — это простая и эффективная библиотека для создания 2D игр на языке Go. Она предоставляет удобные инструменты для рисования графики, обработки ввода и управления анимациями.

Установка и настройка

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

go get -u github.com/hajimehoshi/ebiten/v2

После установки библиотеки вы готовы начать создавать свою игру!

Пример игры «Платформер»

Давайте создадим игру «Платформер», где игрок управляет персонажем, преодолевая препятствия.

Шаг 1: Подключение необходимых пакетов

package main  import ( "github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2/ebitenutil" "github.com/hajimehoshi/ebiten/v2/inpututil" "github.com/hajimehoshi/ebiten/v2/vector" "image/color" )

Этот блок кода импортирует необходимые пакеты для работы с библиотекой Ebiten. В нем используются ebiten для создания игры, ebitenutil для загрузки изображений, inpututil для обработки ввода с клавиатуры и vector для рисования графики.

Шаг 2: Определение констант и переменных

const ( screenWidth  = 2000    // Ширина игрового экрана screenHeight = 700     // Высота игрового экрана )  var ( playerImage     *ebiten.Image  // Изображение игрока backgroundImage *ebiten.Image  // Фоновое изображение playerX         = 0            // Координата X игрока на экране playerY         = 0            // Координата Y игрока на экране jumping         = false        // Флаг прыжка игрока jumpVelocity    = 0            // Скорость прыжка игрока gravity         = 3            // Сила гравитации groundLevel     = 630          // Уровень земли, на котором находится игрок  obstacleX      = 250  // Координата X первого препятствия obstacleY      = 350  // Координата Y первого препятствия obstacleWidth  = 40   // Ширина первого препятствия obstacleHeight = 40   // Высота первого препятствия  obstacle2X      = 460  // Координата X второго препятствия obstacle2Y      = 350  // Координата Y второго препятствия obstacle2Width  = 40   // Ширина второго препятствия obstacle2Height = 40   // Высота второго препятствия ) 

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

Шаг 3: Определение структуры игры и методов ее обновления и отрисовки

type Game struct{}  func (g *Game) Update() error { // Обновление игрового состояния }  func (g *Game) Draw(screen *ebiten.Image) { // Отрисовка игровых объектов }  func (g *Game) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeight int) { return outsideWidth, outsideHeight } 

В этом блоке кода определяется структура Game, которая представляет игру. Метод Update используется для обновления игрового состояния, Draw — для отрисовки игровых объектов, а Layout — для установки размеров экрана.

Шаг 4: Обновление игрового состояния

func (g *Game) Update() error { if inpututil.IsKeyJustPressed(ebiten.KeyEscape) { return nil // Закрываем игру, возвращая nil }  // Управление игроком if ebiten.IsKeyPressed(ebiten.KeyLeft) { playerX -= 10 // Смещаем игрока влево при нажатии клавиши влево } if ebiten.IsKeyPressed(ebiten.KeyRight) { playerX += 10 // Смещаем игрока вправо при нажатии клавиши вправо } if ebiten.IsKeyPressed(ebiten.KeyUp) { if !jumping { // Если игрок не в состоянии прыжка jumping = true     // Устанавливаем флаг прыжка jumpVelocity = 50  // Устанавливаем скорость прыжка } }  // Прыжок игрока if jumping { playerY -= jumpVelocity   // Обновляем положение игрока по вертикали jumpVelocity -= gravity   // Уменьшаем скорость прыжка из-за гравитации if playerY > groundLevel { // Если игрок достиг земли playerY = groundLevel  // Устанавливаем его на уровень земли jumping = false        // Сбрасываем флаг прыжка } } else if playerY < groundLevel { // Если игрок находится в воздухе выше уровня земли playerY = groundLevel // Устанавливаем его на уровень земли }  // Ограничение перемещения игрока в пределах экрана if playerX < 0 { playerX = 0 // Не даем игроку выйти за левую границу экрана } if playerX > screenWidth-16 { playerX = screenWidth - 16 // Не даем игроку выйти за правую границу экрана } if playerY < 0 { playerY = 0 // Не даем игроку выйти за верхнюю границу экрана } if playerY > screenHeight-16 { playerY = screenHeight - 16 // Не даем игроку выйти за нижнюю границу экрана }  // Проверка коллизий с препятствиями if checkCollision(playerX, playerY, 16, 16, obstacleX, obstacleY, obstacleWidth, obstacleHeight) { // Если произошла коллизия с первым препятствием playerX = obstacleX - 16 // Устанавливаем игрока перед препятствием playerY = obstacleY - 16 // Устанавливаем игрока на верхний край препятствия }  if checkCollision(playerX, playerY, 16, 16, obstacle2X, obstacle2Y, obstacle2Width, obstacle2Height) { // Если произошла коллизия со вторым препятствием playerX = obstacle2X - 16 // Устанавливаем игрока перед вторым препятствием playerY = obstacle2Y - 16 // Устанавливаем игрока на верхний край второго препятствия }  return nil } //Вспомогательная функция для проверки коллизий func checkCollision(x1, y1, w1, h1, x2, y2, w2, h2 int) bool { return x1 < x2+w2 && x1+w1 > x2 && y1 < y2+h2 && y1+h1 > y2 } 

Эта функция обновляет состояние игры каждый кадр, обрабатывает пользовательский ввод и обновляет положение игрока на основе нажатых клавиш. Она также обрабатывает прыжки игрока, гравитацию и проверку коллизий с препятствиями, чтобы предотвратить перемещение игрока через препятствия. Функция checkCollision проверяет, пересекаются ли два прямоугольника (игрок и препятствие) в пространстве.

Шаг 5: Отрисовка игровых объектов

func (g *Game) Draw(screen *ebiten.Image) { // Отображение фонового изображения с уменьшением размера в два раза op := &ebiten.DrawImageOptions{} op.GeoM.Scale(0.8, 0.7) // Уменьшение размера в два раза screen.DrawImage(backgroundImage, op)  // Рисование игрока с уменьшением размера в два раза geoM := ebiten.GeoM{} geoM.Translate(float64(playerX), float64(playerY)) geoM.Scale(0.4, 0.4) // Уменьшение размера в два раза screen.DrawImage(playerImage, &ebiten.DrawImageOptions{GeoM: geoM})  // Рисование препятствия 1 vector.DrawFilledRect(screen, float32(obstacleX), float32(obstacleY), float32(obstacleWidth), float32(obstacleHeight), color.Gray{}, false)  // Рисование препятствия 2 vector.DrawFilledRect(screen, float32(obstacle2X), float32(obstacle2Y), float32(obstacle2Width), float32(obstacle2Height), color.Gray{}, false)  } 

Эта функция отображает фоновое изображение, изображение игрока и два препятствия на экране. Она использует методы из библиотеки Ebiten для отрисовки изображений и векторных прямоугольников на экране игры.

Шаг 6: Запуск игры

func main() { // Загрузка изображения игрока img, _, err := ebitenutil.NewImageFromFile("person.png") if err != nil { panic(err) } playerImage = img  // Загрузка фонового изображения backgroundImage, _, err = ebitenutil.NewImageFromFile("Game_Background.png") if err != nil { panic(err) }  playerX = 50 // Персонаж начинает игру немного правее  // Запуск игры game := &Game{} if err := ebiten.RunGame(game); err != nil { panic(err) } }
Особенности игры:

Особенности игры:
  • Управление игроком: Игрок может управлять персонажем с помощью клавиш клавиатуры, перемещая его влево, вправо и выполняя прыжки.

  • Гравитация и прыжок: Есть гравитация, которая воздействует на персонажа, а также возможность выполнять прыжки.

  • Ограничение перемещения: Игрок не может выйти за пределы экрана.

  • Коллизии с препятствиями: Есть несколько препятствий на уровне, и персонаж не может пройти сквозь них.

Вывод

В результате создания этой игры вы получили работающий прототип с простой механикой и управлением. Даже на основе этого простого примера можно увидеть потенциал Ebiten для создания более сложных игр.

Вы можете найти полный исходный код этого проекта на GitHub


ссылка на оригинал статьи https://habr.com/ru/articles/798917/