Решил попробовать пописать простые 2D игры на Golang. Основная цель — развлечение и более углубленное понимание того как можно писать простые любительские 2D игры на Go.
В начале пути
Скорее всего это будет цикл небольших, но полезных статей для всех интересующихся 2D играми и Golang. Первое, что нам необходимо решить — каким инструментом мы будем пользоваться для разработки игры. Я остановился на довольно простом игровом фреймворке — Ebiten. Основная идея библиотеки — все что есть это просто изображение. Порядок, позиция, угол наклона и масштаб зависит от вашей игровой логики.
Игровой цикл:
- Инициализация игровых объектов
- Повторить:
- Проверка пользовательского ввода, данных по сети.
- Обновление игрового мира (один тик)
- Отрисовка
Цикл повторяется много много раз в секунду (тики): обновление координат игроков в зависимости от игровой логики, отрисовка и так далее. Итого задача сводится к инициализации игрового мира, ведения расчетов и отрисовки.
В Ebiten это сделано довольно элегантно. Ниже мой измененный пример базовой игровой структуры:
type Object struct { x, y int img *ebiten.Image } func main() { var err error dir, err := os.Getwd() img, _, err := ebitenutil.NewImageFromFile(dir+"/assets/ball.png", ebiten.FilterDefault) firstPlayer := &Object{img: img} img, _, err = ebitenutil.NewImageFromFile(dir+"/assets/ball.png", ebiten.FilterDefault) secondPlayer := &Object{img: img} if err != nil { log.Fatal(err) } ebiten.SetWindowSize(screenXMax*2, screenYMax*2) ebiten.SetWindowTitle("Ball Bouncer") g := NewGame(fristPlayer,secondPlayer) if err := ebiten.RunGame(g); err != nil { log.Fatal(err) } }
Итого вся логика будет написана в нашей структуре Game:
const ( // Screen resolution screenXMax = 500 screenYMax = 580 ) type Game struct { scoreFirst, scoreSecond int firstPlayer, secondPlayer *Object } func (g *Game) Update(screen *ebiten.Image) error { // Here our update logic: checking player position, handler user inputs etc... return nil } func (g *Game) Draw(screen *ebiten.Image) { screen.Fill(color.RGBA{0, 0xff, 0, 0xff}) // Here we just draw our players and other assets } func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) { return screenXMax, screenYMax }
В следующих статьях рассмотрим более подробнее пользовательское взаимодействие, отрисовку игровых объектов, расчет коллизий.