diff options
author | Benjamin Chausse <benjamin@chausse.xyz> | 2024-07-11 12:17:02 -0400 |
---|---|---|
committer | Benjamin Chausse <benjamin@chausse.xyz> | 2024-07-11 12:17:02 -0400 |
commit | c6877f2ca4fdd03c4282e1aa3c9b32358c9ad6ad (patch) | |
tree | 0358a4ec4c39860bf6e7acb2173b0762ab2913f9 /internal/pacman/pacman.go |
Initial Commit
Diffstat (limited to 'internal/pacman/pacman.go')
-rw-r--r-- | internal/pacman/pacman.go | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/internal/pacman/pacman.go b/internal/pacman/pacman.go new file mode 100644 index 0000000..cb663af --- /dev/null +++ b/internal/pacman/pacman.go @@ -0,0 +1,152 @@ +package pacman + +import ( + "time" + + "github.com/ChausseBenjamin/pacgo/internal/render" +) + +type Direction uint8 + +const ( + UP Direction = iota + DOWN + LEFT + RIGHT +) + +type Pacman struct { + renderer *render.Renderer + + bright bool + x float64 + y float64 + dir Direction + refreshRate int // times/second the position is updated + + vSpeed float64 // tiles per second + hSpeed float64 // tiles per second + moveTicker *time.Ticker + moveDone chan bool + + blinkRate float64 // stateChanges per second + blinkTicker *time.Ticker + blinkDone chan bool +} + +func (p *Pacman) blink() { + p.bright = !p.bright +} + +func (p *Pacman) drawInstruction() render.DrawInstruction { + return render.DrawInstruction{ + X: int(p.x), + Y: int(p.y), + Content: p.Icon(), + } +} + +// clear will remove the pacman from the screen. This is useful in two cases: +// - Remove pacman's trail/previous position +// - Remove pacman from the screen on death/level change/etc. +// This function will not update pacman's position. This means it must be +// called before updating the position. +func (p *Pacman) clearInstruction() render.ClearInstruction { + return render.ClearInstruction{ + X: int(p.x), + Y: int(p.y), + Size: 1, + } +} + +// move will update pacman's position constantly +// based on the direction it is facing. +func (p *Pacman) move() { + p.renderer.Push(p.clearInstruction()) + switch p.dir { + case UP: + p.y -= (float64(p.vSpeed) * float64(p.refreshRate)) / 1000 + case DOWN: + p.y += (float64(p.vSpeed) * float64(p.refreshRate)) / 1000 + case LEFT: + p.x -= (float64(p.hSpeed) * float64(p.refreshRate)) / 1000 + case RIGHT: + p.x += (float64(p.hSpeed) * float64(p.refreshRate)) / 1000 + } + p.renderer.Push(p.drawInstruction()) +} + +func (p *Pacman) Pos() (float64, float64) { + return p.x, p.y +} + +func (p *Pacman) Redirect(dir Direction) { + p.dir = dir +} + +func (p *Pacman) Icon() string { + icns := map[Direction]map[bool]string{ + UP: {true: "", false: ""}, + DOWN: {true: "", false: ""}, + LEFT: {true: "", false: ""}, + RIGHT: {true: "", false: ""}, + } + + return icns[p.dir][p.bright] +} + +func (p *Pacman) Start() { + p.blinkDone = make(chan bool) + p.moveDone = make(chan bool) + // fmt.Println(time.Duration(1/p.blinkRate) * time.Second) + blinkTicker := time.NewTicker(time.Duration(float64(time.Second) / p.blinkRate)) + moveTicker := time.NewTicker(time.Duration(float64(time.Second) / float64(p.refreshRate))) + + go func() { + for { + select { + case <-blinkTicker.C: + p.blink() + case <-moveTicker.C: + p.move() + case <-p.blinkDone: + return + case <-p.moveDone: + return + } + } + }() +} + +func (p *Pacman) Stop() { + p.blinkTicker.Stop() + p.moveTicker.Stop() + p.blinkDone <- true + p.moveDone <- true +} + +func NewPacman(x float64, y float64, rdr *render.Renderer) *Pacman { + p := &Pacman{x: x, y: y} + p.dir = RIGHT + p.refreshRate = 200 + p.vSpeed = 0.1 + p.hSpeed = 0.2 + p.blinkRate = 3 + p.renderer = rdr + go p.blink() + go p.move() + return p +} + +// // Icons +// pub const PACMAN_UP_ON :char = ''; +// pub const PACMAN_DOWN_ON :char = ''; +// pub const PACMAN_LEFT_ON :char = ''; +// pub const PACMAN_RIGHT_ON :char = ''; +// pub const GHOST_ON :char = ''; + +// pub const PACMAN_UP_OFF :char = ''; +// pub const PACMAN_DOWN_OFF :char = ''; +// pub const PACMAN_LEFT_OFF :char = ''; +// pub const PACMAN_RIGHT_OFF :char = ''; +// pub const GHOST_OFF :char = ''; |