package game import ( "client/client" "client/elements" "client/fonts" "client/gamedata" "client/pb" "fmt" "maps" "sync" "time" "github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2/text/v2" "golang.org/x/exp/rand" ) var ( screenWidth = 640 screenHeight = 480 namelist = []string{"slappy", "mick", "rodney", "george", "ringo", "robin", "temitry "} ) func init() { rand.Seed(uint64(time.Now().UnixNano())) } type ClientData struct { Id int Address string Name string Position gamedata.Coordinates Hit bool } type Game struct { name string blocky *elements.Block hitblocky *elements.Block gameId int //players map[client.Identity] clients map[string]ClientData gameclient *client.Client cycle int position gamedata.Coordinates mu sync.Mutex } func NewGame() *Game { g := &Game{ gameclient: client.NewClient(), blocky: elements.NewBlock(), hitblocky: elements.NewBlock(), cycle: 0, name: namelist[rand.Intn(len(namelist))], } g.hitblocky.SetHit(true) g.clients = make(map[string]ClientData) //g.gameId = g.gameclient.GetIdentity() go g.gameclient.ReadData(g.HandleServerData) return g } func (g *Game) Update() error { x, y := ebiten.CursorPosition() g.position.X = float64(x) g.position.Y = float64(y) g.blocky.SetPosition(g.position) //broadcast our position if g.cycle%2 == 0 { if g.gameclient.IsConnected() { //g.gameclient.SendData(fmt.Sprintf("%s,%.0f,%.0f\n", g.name, g.position.X, g.position.Y)) cd := &pb.ClientCoordinates{ Name: g.name, Coordinates: &pb.Coordinates{ X: g.position.X, Y: g.position.Y, }, } envelope := &pb.ClientEnvelope{ Payload: &pb.ClientEnvelope_Coordinates{ Coordinates: cd, }, } g.gameclient.SendMessage(envelope) //g.gameclient.SendProtoData(cd) /* cd := *client.ClientData{ Name: g.name, Address: g. }*/ } } //cleanup client list every 2 seconds if g.cycle%120 == 0 { go g.CleanupClients() } g.cycle++ return nil } func (g *Game) Draw(screen *ebiten.Image) { screen.Clear() g.blocky.Draw() g.hitblocky.Draw() op := &ebiten.DrawImageOptions{} op.GeoM.Translate(-float64(g.blocky.Sprite.Bounds().Dx())/2, -float64(g.blocky.Sprite.Bounds().Dy())/2) op.GeoM.Translate(g.blocky.GetPosition().X, g.blocky.GetPosition().Y) screen.DrawImage(g.blocky.Sprite, op) f2 := &text.GoTextFace{ Source: fonts.LaunchyFont.New, Size: 12, } top := &text.DrawOptions{} top.GeoM.Translate(g.blocky.GetPosition().X-50, g.blocky.GetPosition().Y+15) text.Draw(screen, "you ("+g.name+")", f2, top) g.mu.Lock() clientcopy := maps.Clone(g.clients) g.mu.Unlock() for _, client := range clientcopy { op := &ebiten.DrawImageOptions{} op.GeoM.Translate(-float64(g.blocky.Sprite.Bounds().Dx())/2, -float64(g.blocky.Sprite.Bounds().Dy())/2) op.GeoM.Translate(client.Position.X, client.Position.Y) if !client.Hit { screen.DrawImage(g.blocky.Sprite, op) } else { screen.DrawImage(g.hitblocky.Sprite, op) } f2 := &text.GoTextFace{ Source: fonts.LaunchyFont.New, Size: 12, } top := &text.DrawOptions{} top.GeoM.Translate(client.Position.X, client.Position.Y) text.Draw(screen, client.Name, f2, top) } } func (g *Game) Layout(outsideWidth, outsideHeight int) (screenwidth, screenheight int) { return screenWidth, screenHeight } func (g *Game) HandleServerData(envelope *pb.ServerEnvelope) { switch payload := envelope.Payload.(type) { case *pb.ServerEnvelope_Broadcast: //fmt.Println("Here comes the broadcast!") for _, client := range payload.Broadcast.Clients { if client.Id != int32(g.gameId) { update := ClientData{ Id: int(client.Id), Address: client.Address, Name: client.Name, Position: gamedata.Coordinates{ X: client.Coordinates.X, Y: client.Coordinates.Y, }, Hit: client.Hit, } g.mu.Lock() g.clients[update.Address] = update g.mu.Unlock() } } case *pb.ServerEnvelope_Identity: fmt.Println("Server is trying to give us our id.") g.gameId = int(payload.Identity.Id) } } func (g *Game) CleanupClients() { g.mu.Lock() for k := range g.clients { delete(g.clients, k) } g.mu.Unlock() }