func main() { err := graphics.Init() if err != nil { log.Fatalln(err) } defer graphics.Quit() win, err := graphics.CreateWindow(800, 600, "Test") if err != nil { log.Fatalln(err) } defer win.Destroy() if len(os.Args) == 1 { newBackEnd() } frontend := NewPlayerFrontend(win) if len(os.Args) == 1 { joinEvent := &events.PlayerJoin{ UUID: frontend.id, } events.SendEvent(joinEvent) go StartNetworkListener() loadlevel := events.LoadLevel{ FileName: "assets/testTiles.json", } events.SendEvent(&loadlevel) } else { NewNetworkBackend(os.Args[1]) } frontend.Mainloop() }
func NewNetworkFrontend(conn net.Conn) *NetworkFrontend { n := NetworkFrontend{ Network: Network{ conn: conn, dir: events.DirFront, decoder: json.NewDecoder(conn), eventCh: make(chan events.Event), close: make(chan struct{}), }, } n.afterDestroy = n.sendLeave id, err := uuid.NewV4() if err != nil { log.Fatalln(err) } n.id = id.String() events.AddListener(n.eventCh, events.DirFront, 0) setEvent := &events.SetUUID{ UUID: n.id, } n.sendEvent(setEvent) go n.readloop() go n.mainloop() joinEvent := &events.PlayerJoin{ UUID: n.id, } events.SendEvent(events.ReloadLevel{}) events.SendEvent(joinEvent) return &n }
func (p *PlayerFrontend) Mainloop() { nextUpdate := time.After(10 * time.Microsecond) loop: for { select { case ev := <-p.eventCh: p.processEvent(ev) case <-nextUpdate: nextUpdate = time.After(time.Second / 60) p.processInput() if err := p.window.Update(p.getDraw()); err != nil { log.Fatalln(err) } case _, ok := <-p.close: if !ok { break loop } } } events.RemoveListener(p.eventCh, events.DirFront, 0) for _, v := range p.units { v.Destroy() } leaveEvent := &events.PlayerLeave{ UUID: p.id, } events.SendEvent(leaveEvent) }
func (b *BackEnd) createPlayerUnit(id int, uuid string) { createPlayer := events.CreateUnit{ ID: id, X: b.lastLevel.StartX, Y: b.lastLevel.StartY, W: 32, H: 32, AttachTo: uuid, } events.SendEvent(&createPlayer) }
func (p *PlayerFrontend) sendInput(in Input) { player := p.GetUnit(p.player) if player == nil { return } e := events.InputUpdate{ ID: p.player, X: in.X, Y: in.Y, } events.SendEvent(&e) }
func (n *Network) readloop() { for { var data struct { Type int Event json.RawMessage } err := n.decoder.Decode(&data) if err != nil { if n, ok := err.(net.Error); ok && n.Temporary() { continue } log.Println(err) break } ev, err := events.DecodeJSON(data.Type, data.Event) if err != nil { log.Println(err) break } ev.SetDuplicate(true) events.SendEvent(ev) } }
func (b *BackEnd) processEvent(ev events.Event) { switch e := ev.(type) { case *events.CreateUnit: b.unitInfo = append(b.unitInfo, NewUnit(e.X, e.Y, PlayerT, e.ID, b)) case *events.DestroyUnit: for i, unit := range b.unitInfo { if unit.unitID == e.ID { b.unitInfo = append(b.unitInfo[:i], b.unitInfo[i+1:]...) break } } case *events.ChangeLevel: b.lastLevel = e for _, unit := range b.unitInfo { unit.Destroy() } b.unitInfo = make([]*unit, 0, len(e.Units)) b.nextID = 1 for _, unit := range e.Units { b.processEvent(&unit) if b.nextID <= unit.ID { b.nextID = unit.ID + 1 } } for k, v := range b.players { if _, ok := e.Players[k]; !ok { if b.nextID <= v { b.nextID = v + 1 } b.createPlayerUnit(v, k) } } case events.ReloadLevel: units := make([]events.CreateUnit, len(b.unitInfo)) for i, unit := range b.unitInfo { units[i] = events.CreateUnit{ ID: unit.unitID, X: unit.x, Y: unit.y, W: 32, H: 32, } } newLevel := &events.ChangeLevel{ // TODO Change this to copy the contents of Tilemaps Tilemaps: b.lastLevel.Tilemaps, Images: b.lastLevel.Images, TileWidth: b.lastLevel.TileWidth, TileHeight: b.lastLevel.TileHeight, StartX: b.lastLevel.StartX, StartY: b.lastLevel.StartY, CollideMap: b.lastLevel.CollideMap, Pits: b.lastLevel.Pits, Units: units, Players: b.players, } events.SendEvent(newLevel) case *events.PlayerJoin: id := b.nextID b.players[e.UUID] = id b.nextID++ if b.lastLevel == nil { return } b.createPlayerUnit(id, e.UUID) case *events.LoadLevel: b.loadLevel(e) case *events.PlayerLeave: destroy := events.DestroyUnit{ ID: b.players[e.UUID], } events.SendEvent(&destroy) delete(b.players, e.UUID) } }
func (b *BackEnd) loadLevel(e *events.LoadLevel) { type level struct { Height int32 Width int32 Tileheight int32 Tilewidth int32 Layers []struct { Data []int Properties map[string]string Height int32 Width int32 } Tilesets []struct { Image string Tilewidth int32 Tileheight int32 Tileproperties map[string]map[string]string } Properties map[string]string } file, err := os.Open(e.FileName) if err != nil { log.Printf("failed loading file: %s\n", e.FileName) return } defer file.Close() var x level err = json.NewDecoder(file).Decode(&x) if err != nil { log.Printf("failed loading file: %s\n", e.FileName) return } //changeLevel struct //load the change startX, err := strconv.Atoi(x.Properties["StartX"]) startY, err := strconv.Atoi(x.Properties["StartY"]) cLevel := events.ChangeLevel{ Tilemaps: make([]events.Tilemap, 0, len(x.Tilesets)), Images: [][][]int{}, TileWidth: x.Tilewidth, TileHeight: x.Tileheight, StartX: float64(startX)*float64(x.Tilewidth) + float64(x.Tilewidth)*.5, StartY: float64(startY)*float64(x.Tileheight) + float64(x.Tileheight)*.5, CollideMap: make([][]bool, x.Height), Units: make([]events.CreateUnit, 0, len(b.players)), Players: map[string]int{}, Pits: make([][]bool, x.Height), } b.nextID = 1 for playerID := range b.players { create := events.CreateUnit{ ID: b.nextID, X: cLevel.StartX, Y: cLevel.StartY, W: 32, H: 32, AttachTo: playerID, } b.players[playerID] = b.nextID cLevel.Players[playerID] = b.nextID cLevel.Units = append(cLevel.Units, create) b.nextID++ } for i := range cLevel.CollideMap { cLevel.CollideMap[i] = make([]bool, x.Width) cLevel.Pits[i] = make([]bool, x.Width) } for _, t := range x.Tilesets { tm := events.Tilemap{ Filename: t.Image, TileWidth: t.Tilewidth, TileHeight: t.Tileheight, } cLevel.Tilemaps = append(cLevel.Tilemaps, tm) } for z, layer := range x.Layers { cLevel.Images = append(cLevel.Images, [][]int{}) var i int32 for i = 0; i < layer.Height; i++ { cLevel.Images[z] = append(cLevel.Images[z], layer.Data[i*layer.Width:(i+1)*layer.Width]) } for yC, row := range cLevel.Images[z] { for xC, tile := range row { for _, tileset := range x.Tilesets { for k, v := range tileset.Tileproperties { if v["Pit"] == "True" { if strconv.Itoa(tile-1) == k { cLevel.Pits[yC][xC] = true } } } } if layer.Properties["collide"] == "true" { if tile != 0 { cLevel.CollideMap[yC][xC] = true } } } } } events.SendEvent(&cLevel) }
func (n *NetworkFrontend) sendLeave() { leave := events.PlayerLeave{ UUID: n.id, } events.SendEvent(&leave) }
//has to do with everything about the unit func (u *unit) updateUnit() { curRect := u.typ.hitDetect.collisionBox(int32(u.x), int32(u.y)) newX := u.x + u.xV if u.xV > 0 { //right currBox := curRect.rightBox currBox.right += int32(u.xV) tileX, _ := currBox.checkRect(u.backAccess.lastLevel.CollideMap, 1, 0, u.backAccess.lastLevel.TileWidth, u.backAccess.lastLevel.TileHeight) if tileX != -1 { newX = float64(int32(tileX)*u.backAccess.lastLevel.TileWidth - u.typ.hitDetect.rightBox.right - 1) u.xV = 0 } } else { //left currbox := curRect.leftBox currbox.left += int32(u.xV) tileX, _ := currbox.checkRect(u.backAccess.lastLevel.CollideMap, -1, 0, u.backAccess.lastLevel.TileWidth, u.backAccess.lastLevel.TileHeight) if tileX != -1 { newX = float64(int32(tileX+1)*u.backAccess.lastLevel.TileWidth - u.typ.hitDetect.leftBox.left) u.xV = 0 } } curRect = u.typ.hitDetect.collisionBox(int32(newX), int32(u.y)) newY := u.y + u.yV if u.yV > 0 { //down currbox := curRect.bottomBox currbox.bottom += int32(u.yV) _, tileY := currbox.checkRect(u.backAccess.lastLevel.CollideMap, 0, 1, u.backAccess.lastLevel.TileWidth, u.backAccess.lastLevel.TileHeight) if tileY != -1 { newY = float64(int32(tileY)*u.backAccess.lastLevel.TileHeight - u.typ.hitDetect.bottomBox.bottom - 1) u.yV = 0 } } else { //up currBox := curRect.topBox currBox.top += int32(u.yV) _, tileY := currBox.checkRect(u.backAccess.lastLevel.CollideMap, 0, -1, u.backAccess.lastLevel.TileWidth, u.backAccess.lastLevel.TileHeight) if tileY != -1 { newY = float64(int32(tileY+1)*u.backAccess.lastLevel.TileHeight - u.typ.hitDetect.topBox.top) u.yV = 0 } } u.x = newX u.y = newY u.xV += u.xAcl + (-u.xV * 0.8) u.yV += u.yAcl + (-u.yV * 0.8) if u.backAccess.lastLevel.Pits[int32(u.y)/u.backAccess.lastLevel.TileHeight][int32(u.x)/u.backAccess.lastLevel.TileWidth] { u.x = u.backAccess.lastLevel.StartX u.y = u.backAccess.lastLevel.StartY u.xV = 0 u.yV = 0 } e := events.UnitMoved{ ID: u.unitID, NewX: u.x, NewY: u.y, } events.SendEvent(&e) }