Skip to content

Commit

Permalink
Enemies that follow the hero added
Browse files Browse the repository at this point in the history
  • Loading branch information
barisbll committed Oct 1, 2023
1 parent 6f9858f commit ca85ea8
Show file tree
Hide file tree
Showing 5 changed files with 182 additions and 10 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.vscode
TODO
TODO
hero-go
4 changes: 4 additions & 0 deletions bomb.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,14 @@ func calculateFinalPosition(maxX, maxY, currentX, currentY, distanceX, distanceY

func (b *Bomb) draw(s tcell.Screen, style tcell.Style, ticker *time.Ticker, bombExploded chan string, explosionComplete chan struct{}, explosionWaitGroup *sync.WaitGroup) {
go func() {
// wait until bomb explodes
time.Sleep(b.explodeIn)
// send two signal to the bombExploded channel to hero and bomb itself
bombExploded <- ""
bombExploded <- ""
// Make the explosion animation stay for a second
time.Sleep(1 * time.Second)
// Finish the explosion animation
close(explosionComplete)
}()

Expand Down
114 changes: 114 additions & 0 deletions enemy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package main

import (
"math/rand"
"time"

tcell "github.com/gdamore/tcell/v2"
)

var enemyEmojis = []rune{'👹', '👾', '👽', '👻', '🤡'}

func giveRandomEnemyEmoji() rune {
return enemyEmojis[rand.Intn(len(enemyEmojis))]
}

func giveRandomLocation(maxWidth, maxHeight int) (int, int) {
direction := rand.Intn(4)
switch direction {
case 0:
return rand.Intn(maxWidth), 0
case 1:
return rand.Intn(maxWidth), maxHeight - 1
case 2:
return 0, rand.Intn(maxHeight)
case 3:
return maxWidth - 1, rand.Intn(maxHeight)
}
return 0, 0
}

type Enemy struct {
id int
currentX int
currentY int
speed uint8
isDead bool
emoji rune
hero *Hero
lastDrawnPosition Coordinates
}

func NewEnemy(id, maxWidth, maxHeight int, hero *Hero) *Enemy {
x, y := giveRandomLocation(maxWidth, maxHeight)
return &Enemy{
id: id,
currentX: x,
currentY: y,
speed: 1,
isDead: false,
emoji: giveRandomEnemyEmoji(),
hero: hero,
lastDrawnPosition: Coordinates{x: 0, y: 0},
}
}

func (e *Enemy) move() {
if e.isDead || e.hero.isDead {
return
}

if e.currentX == e.hero.x && e.currentY == e.hero.y {
e.isDead = true
e.hero.isDead = true
return
}

xDifference := makePositive(e.currentX - e.hero.x)
yDifference := makePositive(e.currentY - e.hero.y)

if xDifference >= yDifference {
if e.currentX < e.hero.x {
e.currentX += 1
} else if e.currentX > e.hero.x {
e.currentX -= 1
}
return
} else if xDifference < yDifference {
if e.currentY < e.hero.y {
e.currentY += 1
} else if e.currentY > e.hero.y {
e.currentY -= 1
}
}

}

func (e *Enemy) draw(s tcell.Screen, style tcell.Style, ticker *time.Ticker) {
go func() {
for {
select {
case <-ticker.C:
s.SetContent(e.lastDrawnPosition.x, e.lastDrawnPosition.y, ' ', nil, style)
if !e.isDead {
e.lastDrawnPosition.x = e.currentX
e.lastDrawnPosition.y = e.currentY
s.SetContent(e.lastDrawnPosition.x, e.lastDrawnPosition.y, e.emoji, nil, style)
e.move()
} else {
s.SetContent(e.currentX, e.currentY, DeadEmoji, nil, style)
ticker.Stop()
s.Show()
// Make the dead animation stay for a second
time.Sleep(1 * time.Second)
s.SetContent(e.currentX, e.currentY, ' ', nil, style)
s.Show()
return
}

s.Show()

}
}
}()
}
69 changes: 60 additions & 9 deletions hero.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ const HeroEmoji rune = '\U0001F9B8' // 🦸‍♂️
const DeadEmoji rune = '\U0001F480' // 💀

type Hero struct {
x int
y int
speed uint8
bombs []Bomb
bombIdCounter int
isDead bool
x int
y int
speed uint8
bombs []Bomb
bombIdCounter int
isDead bool
enemies []Enemy
enemyIdCounter int
}

func (h *Hero) goRight(maxWidth int) {
Expand Down Expand Up @@ -66,6 +68,14 @@ func (h *Hero) draw(s tcell.Screen, style tcell.Style) {
}

s.SetContent(h.x, h.y, HeroEmoji, nil, style)

for _, enemy := range h.enemies {
if enemy.isDead {
continue
}

s.SetContent(enemy.currentX, enemy.currentY, enemy.emoji, nil, style)
}
}

func (h *Hero) addBomb(s tcell.Screen, style tcell.Style, clickedX, clickedY int) {
Expand Down Expand Up @@ -130,22 +140,63 @@ func (h *Hero) addBomb(s tcell.Screen, style tcell.Style, clickedX, clickedY int

}

func (h *Hero) isNearBomb(bombX, bombY, actorX, actorY int) bool {
func (h *Hero) isNearBomb(bombX, bombY, actorX, actorY, distance int) bool {
distanceX := makePositive(bombX - actorX)
distanceY := makePositive(bombY - actorY)

if distanceX <= 2 && distanceY <= 2 {
if distanceX <= distance && distanceY <= distance {
return true
}

return false
}

func (h *Hero) killTheThingsInTheExplosionArea(s tcell.Screen, style tcell.Style, bombX, bombY int) {
if h.isNearBomb(bombX, bombY, h.x, h.y) {
if h.isNearBomb(bombX, bombY, h.x, h.y, 2) {
h.isDead = true
s.SetContent(h.x, h.y, DeadEmoji, nil, style)
s.Show()
}

var indexToRemove int = -1

// Todo: kill the enemies
for i, enemy := range h.enemies {

if h.isNearBomb(bombX, bombY, enemy.currentX, enemy.currentY, 5) {
enemy.isDead = true
s.SetContent(enemy.currentX, enemy.currentY, DeadEmoji, nil, style)
indexToRemove = i
s.Show()
}

if indexToRemove != -1 {
// Create a new slice without the element to remove
h.enemies = append(h.enemies[:indexToRemove], h.enemies[indexToRemove+1:]...)
indexToRemove = -1
}
}
}

func (h *Hero) spanNewEnemies(s tcell.Screen, style tcell.Style, maxWidth, maxHeight int) {
if h.isDead {
return
}

enemySpanTicker := time.NewTicker(2 * time.Second)
enemySpeedTicker := time.NewTicker(100 * time.Millisecond)

go func() {
for {
<-enemySpanTicker.C
// for testing purposes
if (len(h.enemies)) >= 1 {
continue
}
enemy := *NewEnemy(h.enemyIdCounter, maxWidth, maxHeight, h)
enemy.draw(s, style, enemySpeedTicker)
h.enemyIdCounter++
h.enemies = append(h.enemies, enemy)
}
}()
}
2 changes: 2 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ func main() {
hero := Hero{x: xmax / 2, y: ymax / 2, speed: 1, isDead: false}

hero.draw(s, defStyle)
hero.spanNewEnemies(s, defStyle, xmax, ymax)

quit := func() {
// You have to catch panics in a defer, clean up, and
Expand Down Expand Up @@ -86,5 +87,6 @@ func main() {
}

hero.draw(s, defStyle)

}
}

0 comments on commit ca85ea8

Please sign in to comment.