Skip to content
This repository has been archived by the owner on May 31, 2024. It is now read-only.

Commit

Permalink
Added a way to determine who is nearby.
Browse files Browse the repository at this point in the history
Started EcoSim example.
  • Loading branch information
GaryBrownEEngr committed Nov 14, 2023
1 parent 96bb022 commit b223730
Show file tree
Hide file tree
Showing 12 changed files with 666 additions and 26 deletions.
148 changes: 148 additions & 0 deletions examples/ecosim/bunny.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package main

import (
"math"
"math/rand"
"time"

"github.com/GaryBrownEEngr/scratch/models"
)

type bunny struct {
sim models.Scratch
sprite models.Sprite
food *models.NearMeInfo
x, y float64
health float64

wanderX, wanderY float64

spawnCounter int
}

func Main_Bunny(sim models.Scratch, x, y float64) {

s := sim.AddSprite("")
s.Costume("Bunny")
s.SetType(BunnyType)

s.Pos(x, y)
s.Z(1)
s.XYScale(.2, .2)
s.Visible(true)
s.Opacity(100)

b := bunny{
sim: sim,
sprite: s,
x: x,
y: y,
health: 50,
spawnCounter: 200,
}
time.Sleep(time.Millisecond * time.Duration(rand.Intn(1000)))

b.main()
}

func (s *bunny) main() {
// MainSpriteLoop:
for {
time.Sleep(time.Millisecond * 20)
s.health -= .1

switch {
case s.health <= 0:
s.sprite.DeleteSprite()
return
case s.health < 75 && s.findFood():
s.feed()
case s.breed():
//
default:
s.wander()
}

s.sprite.Angle(s.health)
}
}

func (s *bunny) findFood() bool {

if s.food == nil {
aroundMe := s.sprite.WhoIsNearMe(100)
minDis := math.MaxFloat64
for i, o := range aroundMe {
if o.SpriteType == GrassType {
deltaX := o.X - s.x
deltaY := o.Y - s.y
dist := deltaX*deltaX + deltaY*deltaY
if dist < minDis {
minDis = dist
s.food = &aroundMe[i]
}
}
}
}

return s.food != nil
}

func (s *bunny) feed() {
if s.food == nil {
return
}

if s.food.SpriteType != GrassType {
return
}

deltaX := s.food.X - s.x
deltaY := s.food.Y - s.y
dist := math.Sqrt(deltaX*deltaX + deltaY*deltaY)
if dist < 5 {
foodStatus := s.sim.GetSpriteInfoByID(s.food.SpriteID)
if foodStatus.Deleted {
s.food = nil
return
}

s.health = min(100, s.health+25)
s.sim.SendMsg(s.food.SpriteID, GrassHasBeenEaten{})
s.food = nil
return
}

speed := 1.0
deltaX /= dist * speed
deltaY /= dist * speed
s.x += deltaX
s.y += deltaY
s.sprite.Pos(s.x, s.y)
}

func (s *bunny) breed() bool {
if s.health < 90 {
return false
}
s.spawnCounter -= 1
if s.spawnCounter <= 0 {
s.spawnCounter = 200
s.health = 25
go Main_Bunny(s.sim, s.x, s.y)
return true
}
return false
}

func (s *bunny) wander() {
s.wanderX += rand.NormFloat64() * .01
s.wanderY += rand.NormFloat64() * .01

s.wanderX = max(-.5, min(.5, s.wanderX))
s.wanderY = max(-.5, min(.5, s.wanderY))

s.x += s.wanderX
s.y += s.wanderY
s.sprite.Pos(s.x, s.y)
}
76 changes: 76 additions & 0 deletions examples/ecosim/grass.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package main

import (
"math"
"math/rand"
"time"

"github.com/GaryBrownEEngr/scratch/models"
)

type GrassHasBeenEaten struct{}

func Main_Grass(sim models.Scratch, x, y float64) {
time.Sleep(time.Millisecond * time.Duration(rand.Intn(100)))
x = float64(int(x))
y = float64(int(y))

s := sim.AddSprite("")
s.Costume("Grass")
s.SetType(GrassType)

s.Pos(x, y)
s.Z(0)
s.XYScale(10, 10)
s.Visible(true)
s.Opacity(10)

health := 5.0
spawnCountDown := 30

MainSpriteLoop:
for {
time.Sleep(time.Millisecond * 100)

msgs := s.GetMsgs()
for _, msg := range msgs {
switch msg.(type) {
case GrassHasBeenEaten:
health -= 50
}
}

if health <= 0 {
s.DeleteSprite()
return
}

health = min(100, health+1)
s.Opacity(health)
if health == 100 {
spawnCountDown -= 1
if spawnCountDown <= 0 {
spawnCountDown = 30
// spawn more grass
newX := x + (float64(rand.Intn(3))-1)*10
newY := y + (float64(rand.Intn(3))-1)*10

nearMe := sim.WhoIsNearMe(x, y, 20)
for _, o := range nearMe {
if o.SpriteType != GrassType {
continue
}
delta := math.Abs(o.X-newX) + math.Abs(o.Y-newY)
if delta < 1 {
// fmt.Printf("Found matching grass: %v\n", o)
continue MainSpriteLoop
}
}

go Main_Grass(sim, newX, newY)
}
} else {
spawnCountDown = 30
}
}
}
53 changes: 53 additions & 0 deletions examples/ecosim/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package main

import (
"image"
"image/color"

"github.com/GaryBrownEEngr/scratch"
"github.com/GaryBrownEEngr/scratch/models"
"github.com/GaryBrownEEngr/scratch/sprite"
)

var (
SkyBlue color.RGBA = color.RGBA{0x87, 0xCE, 0xEB, 0xFF}
SandyBrown color.RGBA = color.RGBA{0xD2, 0xB4, 0x8C, 0xFF}
LawnGreen color.RGBA = color.RGBA{0x7C, 0xFC, 0x00, 0xFF}
)

const (
UndefinedType int = iota
GrassType
BunnyType
)

func main() {
params := scratch.ScratchParams{Width: 1000, Height: 1000, ShowFPS: true}
scratch.Start(params, simStartFunc)
}

func simStartFunc(sim models.Scratch) {
// Set the background by making a single pixel image and scaling it be be the entire screen.
img := image.NewRGBA(image.Rect(0, 0, 1, 1))
img.Set(0, 0, SandyBrown)
sim.AddCostume(img, "Background")
s := sim.AddSprite("background")
s.Costume("Background")
s.Z(0)
s.Scale(1010)
s.Visible(true)

img = image.NewRGBA(image.Rect(0, 0, 1, 1))
img.Set(0, 0, LawnGreen)
sim.AddCostume(img, "Grass")
sim.AddCostume(sprite.DecodeCodedSprite(sprite.TurtleImage), "Bunny")

for x := 0; x < 100; x += 10 {
go Main_Grass(sim, float64(x), 0)
}

// go Main_Grass(sim, 0, 0)
// go Main_Grass(sim, 50, 0)

go Main_Bunny(sim, 10, 10)
}

0 comments on commit b223730

Please sign in to comment.