more anim progress

This commit is contained in:
Luke Meyers 2020-02-07 14:27:58 -08:00
parent f62e9833db
commit a915310274
5 changed files with 171 additions and 148 deletions

View File

@ -13,7 +13,7 @@ const (
right
)
func doCommand(cmd command, s State, teamID int) State {
func doCommand(cmd command, s State, sOld State, teamID int) State {
da := 1
da += rand.Intn(3) - 1
@ -35,5 +35,5 @@ func doCommand(cmd command, s State, teamID int) State {
b.Lane--
}
return updateBot(s, teamID, *b)
return updateBot(s, sOld, teamID, *b)
}

View File

@ -1,8 +1,98 @@
package game
import (
"log"
)
func UpdateState(s State, sOld State) State {
for i := range s.Teams {
s = doCommand(chooseCommand(s, i), s, sOld, i)
if b := activeBot(s.Teams[i]); b != nil {
s = moveBot(s, i, *b)
}
s = maybePassBaton(s, i)
}
for _, t := range s.Teams {
if b := activeBot(t); b != nil && won(*b, s) {
s.GameOver = true
}
}
return s
}
func maybePassBaton(s State, teamID int) State {
t := s.Teams[teamID]
h := activeBot(t)
if h == nil {
return s
}
for i, b := range t.Bots {
if h.ID >= b.ID || h.Lane != b.Lane {
continue
}
if abs(b.Pos-h.Pos) <= passDistance {
h.v = 0
h.a = 0
s = updateBot(s, s, teamID, *h)
newH := t.Bots[i]
newH.a = baseAccel
t.Baton.HolderID = newH.ID
s = updateTeam(s, t)
return updateBot(s, s, teamID, newH)
}
}
return s
}
func activeBot(t Team) *Bot {
for _, b := range t.Bots {
if b.ID == t.Baton.HolderID {
return &b
}
}
return nil
}
func updateBot(s State, sOld State, teamID int, b Bot) State {
t := s.Teams[teamID]
for i, bb := range t.Bots {
if bb.ID == b.ID {
bots := append([]Bot{}, t.Bots[:i]...)
bots = append(bots, b)
bots = append(bots, t.Bots[i+1:]...)
t.Bots = bots
break
}
}
s = updateTeam(s, t)
return s
}
func updateTeam(s State, t Team) State {
s.Teams = append(s.Teams[:t.id], append([]Team{t}, s.Teams[t.id+1:]...)...)
return s
}
func won(b Bot, s State) bool {
return b.Pos >= Steps
}
func gameOver(s State) bool {
for _, t := range s.Teams {
if t.won {
return true
}
}
return false
}
func abs(n int) int {
if n < 0 {
return -n
}
return n
}
type State struct {
Teams []Team
@ -10,6 +100,40 @@ type State struct {
GameOver bool
}
type Team struct {
id int
Bots []Bot
Baton Baton
won bool
Lane int
}
func (t Team) BatonHolder() *Bot {
for _, b := range t.Bots {
if b.ID == t.Baton.HolderID {
return &b
}
}
return nil
}
type Bot struct {
ID int
Lane int
Pos int
v int
a int
}
type Baton struct {
HolderID int
}
type Obstacle struct {
Lane int
Pos int
}
func NewState() State {
var teams []Team
for i := 0; i < NumTeams; i++ {
@ -53,124 +177,6 @@ func NewState() State {
}
}
type Team struct {
id int
Bots []Bot
Baton Baton
won bool
Lane int
}
func (t Team) BatonHolder() *Bot {
for _, b := range t.Bots {
if b.ID == t.Baton.HolderID {
return &b
}
}
return nil
}
type Bot struct {
ID int
Lane int
Pos int
v int
a int
}
type Baton struct {
HolderID int
}
type Obstacle struct {
Lane int
Pos int
}
func UpdateState(s State) State {
for i, t := range s.Teams {
s = doCommand(chooseCommand(s, i), s, i)
if b := activeBot(t); b != nil {
s = moveBot(s, i, *b)
}
s = maybePassBaton(s, i)
}
for _, t := range s.Teams {
if b := activeBot(t); b != nil && won(*b, s) {
s.GameOver = true
}
}
return s
}
func maybePassBaton(s State, teamID int) State {
t := s.Teams[teamID]
h := activeBot(t)
if h == nil {
return s
}
for i, b := range t.Bots {
if h.ID >= b.ID || h.Lane != b.Lane {
continue
}
if abs(b.Pos-h.Pos) <= passDistance {
log.Printf("team %v pass from %v to %v!", teamID, h.ID, b.ID)
h.v = 0
h.a = 0
s = updateBot(s, teamID, *h)
newH := t.Bots[i]
newH.a = baseAccel
t.Baton.HolderID = newH.ID
s = updateTeam(s, t)
return updateBot(s, teamID, newH)
}
}
return s
}
func activeBot(t Team) *Bot {
for _, b := range t.Bots {
if b.ID == t.Baton.HolderID {
return &b
}
}
return nil
}
func updateBot(s State, teamID int, b Bot) State {
t := s.Teams[teamID]
for i, bb := range t.Bots {
if bb.ID == b.ID {
t.Bots = append(t.Bots[:i], append([]Bot{b}, t.Bots[i+1:]...)...)
break
}
}
return updateTeam(s, t)
}
func updateTeam(s State, t Team) State {
s.Teams = append(s.Teams[:t.id], append([]Team{t}, s.Teams[t.id+1:]...)...)
return s
}
func won(b Bot, s State) bool {
return b.Pos >= Steps
}
func gameOver(s State) bool {
for _, t := range s.Teams {
if t.won {
return true
}
}
return false
}
const (
Steps = 50
numBots = 5
@ -179,10 +185,3 @@ const (
maxA = 3
maxV = 10
)
func abs(n int) int {
if n < 0 {
return -n
}
return n
}

View File

@ -26,7 +26,8 @@ func moveBot(s State, teamID int, b Bot) State {
}
}
return updateBot(s, teamID, b)
s = updateBot(s, s, teamID, b)
return s
}
func collide(pos, lane int, s State) bool {

View File

@ -17,32 +17,50 @@ type RenderState struct {
frame int
}
func Render(rs RenderState, s game.State, w *pixelgl.Window, d time.Duration) RenderState {
//tween := float64(rs.frame) / float64(rs.Frames)
func Render(rs RenderState, sOld, sNew game.State, w *pixelgl.Window, d time.Duration) RenderState {
//log.Println("render")
w.Clear(colornames.Peru)
colors := teamColors(s.Teams)
renderBots(s, w, d, colors)
renderObstacles(s, w)
tween := float64(rs.frame) / float64(rs.Frames)
colors := teamColors(sNew.Teams)
renderBots(sOld, sNew, tween, w, d, colors)
renderObstacles(sNew, w)
rs.frame++
//log.Println("frame", rs.frame)
if rs.frame >= rs.Frames {
rs.Animating = false
}
return rs
}
func renderBots(s game.State, w *pixelgl.Window, d time.Duration, colors map[*game.Team]pixel.RGBA) {
func renderBots(sOld, sNew game.State, tween float64, w *pixelgl.Window, d time.Duration, colors map[*game.Team]pixel.RGBA) {
bounds := w.Bounds()
im := imdraw.New(nil)
for i, t := range s.Teams {
//log.Println("sOld.Teams:", sOld.Teams)
for i, t := range sNew.Teams {
for j, bot := range t.Bots {
c := colors[&s.Teams[i]]
c := colors[&sNew.Teams[i]]
c.R += 0.2 * float64(j)
c.G -= 0.1 * float64(j)
im.Color = c
pos := lanePos(bot.Pos, bot.Lane, botWidth, bounds)
oldBot := sOld.Teams[i].Bots[j]
// log.Println("oldBot:", oldBot)
// log.Println("bot:", bot)
oldPos := lanePos(oldBot.Pos, oldBot.Lane, botWidth, bounds)
newPos := lanePos(bot.Pos, bot.Lane, botWidth, bounds)
// log.Println("oldPos:", oldPos)
// log.Println("newPos:", newPos)
pos := pixel.Vec{
X: oldPos.X + tween*(newPos.X-oldPos.X),
Y: oldPos.Y + tween*(newPos.Y-oldPos.Y),
}
im.Push(pos)
@ -53,6 +71,7 @@ func renderBots(s game.State, w *pixelgl.Window, d time.Duration, colors map[*ga
if t.Bots[j].ID == t.Baton.HolderID {
renderBaton(pos, w)
}
//log.Println("sOld.Teams[i].Bots[j]:", sOld.Teams[i].Bots[j])
}
}
}

20
main.go
View File

@ -1,6 +1,7 @@
package main
import (
"log"
"math/rand"
"relay/game"
"relay/gfx"
@ -29,23 +30,26 @@ func run() {
start := time.Now()
w.Clear(colornames.Peachpuff)
for !w.Closed() && !s.GameOver {
w.Clear(colornames.Peru)
sOld := s
//sOld := s
rs := gfx.RenderState{
Animating: false,
Frames: 3,
}
switch {
case w.JustPressed(pixelgl.KeyQ):
return
case w.JustPressed(pixelgl.KeySpace):
s = game.UpdateState(s)
}
rs := gfx.RenderState{
Animating: true,
Frames: 10,
rs.Animating = true
s = game.UpdateState(s, sOld)
}
for rs.Animating {
rs = gfx.Render(rs, s, w, time.Since(start))
log.Println("anim loop")
rs = gfx.Render(rs, sOld, s, w, time.Since(start))
w.Update()
}
w.Update()
}