Пример #1
0
func appMain(a app.App) {
	inst = a
	for e := range a.Events() {
		switch e := a.Filter(e).(type) {
		case lifecycle.Event:
			onLifecycleEvent(&e)
		case size.Event:
			onSizeEvent(&e)
		case paint.Event:
			onPaintEvent(&e)
		case touch.Event:
			onTouchEvent(&e)
		case key.Event:
			onKeyEvent(&e)
		}
	}
}
Пример #2
0
// ServerMain performs the main routine for the demo server.
func ServerMain(a app.App) {
	background := context.Background()
	remotePt = make(chan rexdemo.RemotePoint, 1)
	demo = NewDemo()

	go RunDiscovery(background, demo)

	var glctx gl.Context
	var sz size.Event
	for e := range a.Events() {
		select {
		case pt := <-remotePt:
			touchX = float32(pt.X * float64(sz.WidthPx))
			touchY = float32(pt.Y * float64(sz.HeightPx))
		default:
		}
		switch e := a.Filter(e).(type) {
		case lifecycle.Event:
			switch e.Crosses(lifecycle.StageVisible) {
			case lifecycle.CrossOn:
				glctx, _ = e.DrawContext.(gl.Context)
				onStart(glctx)
				a.Send(paint.Event{})
			case lifecycle.CrossOff:
				onStop(glctx)
				glctx = nil
			}
		case size.Event:
			sz = e
			touchX = float32(sz.WidthPx / 2)
			touchY = float32(sz.HeightPx / 2)
		case paint.Event:
			if glctx == nil || e.External {
				// As we are actively painting as fast as
				// we can (usually 60 FPS), skip any paint
				// events sent by the system.
				continue
			}

			onPaint(glctx, sz)
			a.Publish()
			// Drive the animation by preparing to paint the next frame
			// after this one is shown.
			a.Send(paint.Event{})
		case touch.Event:
			touchX = e.X
			touchY = e.Y
		}
	}
}
Пример #3
0
// main is the entry point of the application. This is function gets registered
// as the main function of the application.
func (m *Module) main(a app.App) {
	var images *glutil.Images
	var glctx gl.Context
	sz := size.Event{}

	m.Render.InitApp(a)

	ticker := time.NewTicker(time.Second)

	for {
		select {
		case <-ticker.C:
			a.Send(paint.Event{})

		case <-m.Network.Updated():
			m.loaded = true

		case e := <-a.Events():
			switch e := a.Filter(e).(type) {
			case lifecycle.Event:
				glctx, _ = e.DrawContext.(gl.Context)
				if glctx != nil {
					glctx = e.DrawContext.(gl.Context)
					if images != nil {
						images.Release()
					}
					images = glutil.NewImages(glctx)
				}
			case size.Event:
				sz = e
			case paint.Event:
				m.draw(glctx, sz, images)
				a.Publish()
			}
		}
	}
}
Пример #4
0
// ServerMain performs the main routine for the demo server.
func ServerMain(a app.App) {
	background := context.Background()
	remotePt = make(chan rexdemo.RemotePoint, 1)
	demo = NewDemo()

	// initialize the room server and launch the discovery server.
	bestAddr := room.BestAddr()
	if bestAddr != "" {
		log.Printf("[WARN] Unable to locate a good address for binding")
	}
	config := &room.ServerConfig{
		Room: rexdemo.Room,
		Bus:  room.NewBus(background, demo),
		Addr: bestAddr,
	}
	server, err := StartServer(config)
	if err != nil {
		log.Printf("[FATAL] Unable to initialize server: %v", err)
		os.Exit(1)
	}
	go func() {
		err = server.Wait()
		if err != nil {
			log.Printf("[FATAL] Server terminated: %v", err)
			return
		}
	}()
	go RunDiscovery(background, server)

	var glctx gl.Context
	var sz size.Event
	for e := range a.Events() {
		select {
		case pt := <-remotePt:
			touchX = float32(pt.X * float64(sz.WidthPx))
			touchY = float32(pt.Y * float64(sz.HeightPx))
		default:
		}
		switch e := a.Filter(e).(type) {
		case lifecycle.Event:
			switch e.Crosses(lifecycle.StageVisible) {
			case lifecycle.CrossOn:
				glctx, _ = e.DrawContext.(gl.Context)
				onStart(glctx)
				a.Send(paint.Event{})
			case lifecycle.CrossOff:
				onStop(glctx)
				glctx = nil
			}
		case size.Event:
			sz = e
			touchX = float32(sz.WidthPx / 2)
			touchY = float32(sz.HeightPx / 2)
		case paint.Event:
			if glctx == nil || e.External {
				// As we are actively painting as fast as
				// we can (usually 60 FPS), skip any paint
				// events sent by the system.
				continue
			}

			onPaint(glctx, sz)
			a.Publish()
			// Drive the animation by preparing to paint the next frame
			// after this one is shown.
			a.Send(paint.Event{})
		case touch.Event:
			touchX = e.X
			touchY = e.Y
		}
	}
}
Пример #5
0
func repaint(a app.App) {
	a.Send(paint.Event{}) // keep animating
}
Пример #6
0
func (gn *Engine) Run(a app.App) {
	if gn.chatty {
		log.Println("Starting gn Run.")
		log.Print("runtime.GOOS = ", runtime.GOOS)
		log.Print("runtime.GOARCH = ", runtime.GOARCH)
	}
	// TODO(monopole): Send these into App somehow, so
	// the select below can be collapse to just a switch
	// on app events.

	var chMasterCommand <-chan ifc.MasterCommand
	var chPauseDuration <-chan float32
	var chGravity <-chan float32
	var chIncomingBall <-chan *model.Ball
	var chQuit <-chan bool

	holdCount := 0
	chWaiting, chIsReady := gn.enterWaitState()
	var sz size.Event
	for {
		if false && gn.chatty {
			log.Printf(" ")
			log.Printf(" ")
			log.Printf("Re-entering select.")
		}
		select {
		case ready := <-chIsReady:
			log.Printf("Got ready signal = %v", ready)
			if ready {
				chWaiting, chIsReady = nil, nil
				relay := gn.nm.GetRelay()
				chMasterCommand = relay.ChMasterCommand()
				chPauseDuration = relay.ChPauseDuration()
				chGravity = relay.ChGravity()
				chIncomingBall = relay.ChIncomingBall()
				chQuit = relay.ChQuit()
				gn.scn.Start()
				if gn.chatty {
					log.Printf("Started screen.")
				}
				gn.createBall()
				gn.isAlive = true
				if gn.chatty {
					log.Printf("Seem to be alive now.")
				}
				a.Send(paint.Event{})
			} else {
				if gn.chatty {
					log.Printf("Unable to get ready - exiting.")
				}
				if gn.stopMeansReallyStop() {
					return
				}
				chWaiting, chIsReady = gn.enterWaitState()
			}
		case mc := <-chMasterCommand:
			switch mc.Name {
			case "kick":
				gn.kick()
				gn.freeze()
			case "left":
				gn.left()
			case "right":
				gn.right()
			case "random":
				gn.random()
			case "destroy":
				gn.balls = []*model.Ball{}
			default:
				log.Print("Don't understand command %v", mc)
			}
		case <-chQuit:
			gn.stop()
			if gn.stopMeansReallyStop() {
				return
			}
			chWaiting, chIsReady = gn.enterWaitState()
		case pd := <-chPauseDuration:
			gn.pauseDuration = pd
		case g := <-chGravity:
			gn.gravity = g
		case b := <-chIncomingBall:
			nx := b.GetPos().X
			if nx == config.MagicX {
				// Ball came in from center of top
				nx = gn.scn.Width() / 2.0
			} else if nx >= 0 && nx <= fuzzyZero {
				// Ball came in from left.
				nx = 0
			} else {
				// Ball came in from right.
				nx = gn.scn.Width()
			}
			// Assume Y component normalized before teleport.
			ny := b.GetPos().Y * gn.scn.Height()
			b.SetPos(nx, ny)
			// TODO: Adjust velocity per refraction-like rules?
			gn.balls = append(gn.balls, b)
		case dc := <-gn.nm.ChDoorCommand():
			gn.handleDoor(dc)
		case event := <-a.Events():
			switch e := a.Filter(event).(type) {
			case lifecycle.Event:
				switch e.Crosses(lifecycle.StageVisible) {
				case lifecycle.CrossOn:
					if chWaiting == nil {
						log.Panic("Lifecycle trouble")
						return
					}
					if err := gn.scn.SetDrawContext(e.DrawContext); err != nil {
						log.Panic(err)
					}
					log.Print("Passing cycleOn")
					chWaiting <- readyCycleOn
					log.Print("Passed cycleOn")
				case lifecycle.CrossOff:
					gn.scn.Stop()
					gn.stop()
					if gn.stopMeansReallyStop() {
						return
					}
					chWaiting, chIsReady = gn.enterWaitState()
				}
			case paint.Event:
				if gn.isAlive {
					gn.moveBalls()
					gn.scn.Paint(gn.balls)
					a.Publish()
				}
				a.Send(paint.Event{})
			case key.Event: // Aspirationally use keys
				if gn.chatty {
					log.Printf("Key event! %T = %v", e.Code, e.Code)
				}
				switch e.Code {
				case key.CodeQ, key.CodeEscape:
					gn.stop()
					if gn.stopMeansReallyStop() {
						return
					}
					chWaiting, chIsReady = gn.enterWaitState()
				}
			case touch.Event:
				if gn.chatty {
					log.Println("Touch event")
				}
				switch e.Type {
				case touch.TypeBegin:
					holdCount = 1
					gn.beginX = e.X
					gn.beginY = e.Y
					if e.X < magicButtonSideLength && e.Y < magicButtonSideLength {
						if gn.chatty {
							log.Printf("Touched shutdown spot.\n")
						}
						gn.stop()
						if gn.stopMeansReallyStop() {
							return
						}
						chWaiting, chIsReady = gn.enterWaitState()
					}
				case touch.TypeMove:
					holdCount++
				case touch.TypeEnd:
					if gn.chatty {
						log.Printf("holdcount = %d", holdCount)
					}
					if holdCount > 0 && holdCount <= maxHoldCount {
						// If they hold on too long, ignore it.
						dx := float64(e.X - gn.beginX)
						dy := float64(e.Y - gn.beginY)
						mag := math.Sqrt(dx*dx + dy*dy)
						if mag >= minDragLength {
							ndx := float32(dx/mag) * gn.scn.Width() / gn.pauseDuration
							ndy := float32(dy/mag) * gn.scn.Height() / gn.pauseDuration
							b := model.NewBall(nil,
								model.Vec{gn.beginX, gn.beginY},
								model.Vec{ndx, ndy})
							if gn.chatty {
								log.Printf("Sending impulse: %s", b.String())
							}
							gn.applyImpulse(b)
						} else {
							if gn.chatty {
								log.Printf("Mag only %.4f", mag)
							}
						}
					}
					holdCount = 0
				}
			case size.Event:
				// TODO: Adjust velocity on resizes - balls should take the
				// same amount of time to traverse the screen regardless of
				// the size.
				sz = e
				gn.scn.ReSize(float32(sz.WidthPx), float32(sz.HeightPx))
				gn.resetImpulseLimit()
				if gn.chatty && debugShowResizes {
					log.Printf(
						"Resize new w=%.2f, new h=%.2f, maxDsqImpulse = %f.2",
						gn.scn.Width(),
						gn.scn.Height(),
						gn.maxDistSqForImpulse)
				}
				if chWaiting != nil {
					if gn.chatty {
						log.Printf("passing readyResize")
					}
					chWaiting <- readyResize
					if gn.chatty {
						log.Printf("passed readyResize")
					}
				}
			}
		}
	}
}