Решил попробовать пописать простые 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
}
В следующих статьях рассмотрим более подробнее пользовательское взаимодействие, отрисовку игровых объектов, расчет коллизий.