// Update is the regular engine callback. func (cr *crtag) Update(eng vu.Eng, in *vu.Input, s *vu.State) { if in.Resized { cr.cam.SetPerspective(60, float64(s.W)/float64(s.H), 0.1, 50) } dt := in.Dt for press, _ := range in.Down { switch press { case vu.K_W: cr.cam.Move(0, 0, dt*-cr.run, cr.cam.Lookxz()) case vu.K_S: cr.cam.Move(0, 0, dt*cr.run, cr.cam.Lookxz()) case vu.K_A: cr.cam.AdjustYaw(dt * cr.spin) case vu.K_D: cr.cam.AdjustYaw(dt * -cr.spin) case vu.K_B: ball := cr.top.NewPov() ball.SetLocation(-2.5+rand.Float64(), 15, -1.5-rand.Float64()) ball.NewBody(vu.NewSphere(1)) ball.SetSolid(1, 0.9) m := ball.NewModel("gouraud").LoadMesh("sphere").LoadMat("sphere") m.SetColour(rand.Float64(), rand.Float64(), rand.Float64()) case vu.K_Space: body := cr.striker.Body() body.Push(-2.5, 0, -0.5) } } }
// makeSphere creates a sphere at the given x, y, z location and with // the given r, g, b colour. func (rc *rctag) makeSphere(parent vu.Pov, x, y, z float64, r, g, b float32) vu.Pov { sz := 0.5 sp := parent.NewPov() sp.NewBody(vu.NewSphere(sz)) sp.SetLocation(x, y, z) sp.SetScale(sz, sz, sz) model := sp.NewModel("solid").LoadMesh("sphere") model.SetUniform("kd", r, g, b) return sp }
// teleport puts the player back to the starting location, safe from // any sentinels. The up/down and view direction are also reset to // their original values in case the player has lost sight of the maze. func (lvl *level) teleport() { if lvl.player.teleport() { lvl.body.Dispose(vu.BODY) lvl.body.SetLocation(0, 0.5, 10) lvl.body.SetRotation(lin.QI) lvl.cam.SetLocation(0, 0.5, 10) lvl.body.NewBody(vu.NewSphere(0.25)) lvl.body.SetSolid(1, 0) lvl.mp.ani.addAnimation(lvl.newTeleportAnimation()) } }
// Wrap finishes the fade level animation and sets the player position to // a safe and stable location. func (f *fadeLevelAnimation) Wrap() { g := f.g g.lens = &cam{} g.cl.setHudVisible(true) g.cl.body.NewBody(vu.NewSphere(0.25)) g.cl.body.SetSolid(1, 0) x, _, z := g.cl.cam.Location() g.cl.cam.SetLocation(x, 0.5, z) g.lens.pitch = 0 g.cl.cam.SetPitch(g.lens.pitch) g.cl.body.SetLocation(x, 0.5, z) g.cl.body.SetRotation(lin.QI) // set the new game state if appropriate. if f.gameState == screenDeactive || f.gameState == screenActive { g.activate(f.gameState) } f.state = 2 }
// toggleFly is used to flip into and out of flying mode. func (g *game) toggleFly() { g.fly = !g.fly if g.fly { g.last.lx, g.last.ly, g.last.lz = g.cl.cam.Location() g.last.pitch = g.cl.cam.Pitch() g.last.yaw = g.cl.cam.Yaw() g.cl.body.Dispose(vu.BODY) g.dir = g.cl.cam.Lookat() } else { g.lens.pitch = g.last.pitch g.lens.yaw = g.last.yaw g.cl.cam.SetPitch(g.last.pitch) g.cl.cam.SetYaw(g.last.yaw) g.cl.cam.SetLocation(g.last.lx, g.last.ly, g.last.lz) g.cl.body.SetLocation(g.last.lx, g.last.ly, g.last.lz) g.cl.body.SetRotation(g.cl.cam.Lookat()) g.cl.body.NewBody(vu.NewSphere(0.25)) g.cl.body.SetSolid(1, 0) g.dir = g.cl.cam.Lookxz() } }
// activate the current level. Add physics parts to the physics simulation. func (lvl *level) activate(hm healthMonitor) { lvl.player.monitorHealth("game", hm) lvl.player.resetEnergy() lvl.hd.setLevel(lvl) // reset the camera each time, so it is in a known position. lvl.cam.SetLocation(4, 0.5, 10) lvl.player.resetEnergy() // ensure the walls and floor are added to the physics simulation. for _, wall := range lvl.walls { // set the walls collision shape based on (hand copied from) the .obj file. wall.NewBody(vu.NewBox(1, 1, 1)) wall.SetSolid(0, 0) } lvl.floor.NewBody(vu.NewBox(100, 25, 100)) lvl.floor.SetSolid(0, 0.4) lvl.floor.SetLocation(0, -25, 0) // add a physics body for the camera. lvl.body.NewBody(vu.NewSphere(0.25)) lvl.body.SetSolid(1, 0) }
// getBall creates a visible sphere physics body. func (cr *crtag) getBall(p vu.Pov) { p.NewBody(vu.NewSphere(1)) p.SetSolid(1, 0.5) p.NewModel("gouraud").LoadMesh("sphere").LoadMat("sphere") }