2016-11-19 3 views
0

Я хочу, чтобы создать цикл игры в ходе (языки), поэтому я попытался это:Game Loop в Golang

package main 

import (
    "fmt" 
    // "runtime" 
    "sync" 
    "time" 
) 

var v = 0 
var wg sync.WaitGroup 
var sec = 5 

func main() { 
    wg.Add(1) 
    gameLoop() 
    wg.Wait() 
} 

func gameLoop() { 
    time.AfterFunc(16*time.Millisecond, gameLoop) 
    v++ 
    fmt.Println(v) 
    if v == sec*60 { 
     // fmt.Println("Goroutines: ", runtime.NumGoroutine()) 
     panic("err") 
     wg.Done() 
    } 
} 

Эта программа работает на 62.5Hz (16*time.Millisecond), вар sec используется для вызова wg.Done() после 5 секунд и вызвал var v напечатано 300 раз.

вызова panic("err") делает результат так:

panic: err 

goroutine 314 [running]: 
panic(0x493c60, 0xc420094370) 
    /usr/local/go/src/runtime/panic.go:500 +0x1a1 
main.gameLoop() 
    /home/billyzaelani/Desktop/main.go:26 +0x11f 
created by time.goFunc 
    /usr/local/go/src/time/sleep.go:154 +0x44 
exit status 2 

Ну что смысл goroutine 314 [running]? Я использовал 314 goroutine для 5-секундного игрового цикла? как это работает в течение нескольких часов?

Но, если использование программы во время выполнения пакета и печати runtime.NumGoroutine, который возвращает количество goroutine, результат Goroutines: 2

Итак, еще раз, что смысл goroutine 314 [running]? в то время как пакет времени выполнения говорит разные вещи.

Последний один, если кто-то может показать мне лучший способ создать цикл игры в golang, я действительно ценю это, большое спасибо

ответ

5

AfterFunc выполняет зарегистрированную функцию в goroutine. https://golang.org/pkg/time/#AfterFunc

В то время как есть только 2 ходячие программы, выполняемые за один раз, было 314 (возможно, не уверены, как работают идентификаторы goroutine), goroutines по всей программе.


я не считаю это «лучше» способом, но по-другому, и предпочтительный, может быть, чтобы смоделировать игровой цикл как for цикла.

func gameLoop() { 
    tick := time.Tick(16 * time.Millisecond) 

    for { 
     select { 
     case <-tick: 

     } 
    } 
} 

В дополнение к сжато регистрации дела в течение интервала, выбор по каналу позволяет легко моделировать тайм-аут, добавив еще один случай для <-time.After, или для отмены, добавив еще один случай для <-done канала.

+4

его можно даже записать короче: 'для диапазона time.Tick (16 * time.Millisecond) {...}'. И ваше предложение лучше - более компактное, более читаемое, меньшее давление GC, меньше переключателей контекста и, конечно, более идиоматично. –

+0

Ну, я нашел это более элегантным, чем 'time.AfterFunc()'. Спасибо за ответ. – billyzaelani

+0

Это похоже на шаг времени? Работает ли она на 30 кадров в секунду? – majidarif