Beispiel #1
0
func (nm *V23Manager) makeBall(p *model.Player) *model.Ball {
	dx := rand.Float64()
	dy := rand.Float64()
	sign := rand.Float64()
	if sign >= 0.5 {
		dx = -dx
	}
	mag := math.Sqrt(dx*dx + dy*dy)
	return model.NewBall(p,
		model.Vec{config.MagicX, 0},
		model.Vec{float32(dx / mag), float32(dy / mag)})
}
Beispiel #2
0
func (gn *Engine) createBall() {
	if gn.chatty {
		log.Printf("Creating ball.")
	}
	gn.balls = append(
		gn.balls,
		model.NewBall(
			gn.nm.Me(),
			model.Vec{gn.scn.Width() / 2, gn.scn.Height() / 2},
			model.Vec{0, 0}))
	if gn.chatty {
		log.Printf("Created ball.")
	}
}
Beispiel #3
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")
					}
				}
			}
		}
	}
}