Skip to content

Instantly share code, notes, and snippets.

@toomasv
Last active August 28, 2019 08:53
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save toomasv/b4dfcea98898b0c653998e6a05846a6e to your computer and use it in GitHub Desktop.
Save toomasv/b4dfcea98898b0c653998e6a05846a6e to your computer and use it in GitHub Desktop.
Spider and fly
Red [
Date: 28-July-2019
Notes: {Click on window to add flies}
]
bb: [] fc: target: none
web: load %web.png
set-step: func [face][as-pair
face/extra/speed * (cosine face/extra/dir)
face/extra/speed * (sine face/extra/dir)
]
change-pos: func [face][
face/offset + 10 + set-step face
]
new-pos: func [face /announce][
unless within? pos: change-pos face 10x10 480x480 [
until [
face/extra/dir: random 360
face/extra/speed: newspeed
within? pos: change-pos face 10x10 480x480
]
if announce [publish face]
]
face/draw/2: face/extra/dir + 90
face/offset: pos - 10
]
publish: function [face][
either found: find/tail bb face [
found/1: face/offset + 10
found/2: face/extra/dir
found/3: face/extra/speed
][
repend bb [
face
face/offset + 10
face/extra/dir
face/extra/speed
]
]
]
newdata: func [face][
face/offset: 10 + random 480x480
face/extra/dir: random 360
face/extra/speed: newspeed
]
newspeed: does [5 + random 10]
fly-shape: [
rotate 0 10x10 [
pen gray
line 10x1 10x3 ;noseline
line 12x13 13x15 13x18 ;rleg
line 8x13 7x15 7x18 ;lleg
pen off
fill-pen brown ellipse 6x3 8x5 ;head
fill-pen gray ellipse 7x7 6x9 ;body
pen gray
fill-pen white
ellipse 11x9 7x3 ;rwing
ellipse 2x9 7x3 ;lwing
pen off
fill-pen gray
rotate -10 8x3 [ellipse 6x2 3x2] ;reye
rotate 10 12x3 [ellipse 11x2 3x2] ;leye
ellipse 9x1 2x1 ;nose
]
]
spider-shape: [
rotate 0 10x10 [
fill-pen black
ellipse 9x6 3x4 ;head
ellipse 8x10 5x6 ;body
line-width .5
line 10x6 10x4 ;ll1
line 11x6 11x4 ;rl1
line-width 1
line 12x7 14x4 15x1 ;rleg1
line 9x7 7x4 6x1 ;lleg 1
line 12x8 15x7 17x5 ;rleg 2
line 9x8 6x7 4x5 ;lleg 2
line 12x9 15x9 17x10 ;rleg 3
line 9x9 6x9 4x10 ;lleg 3
line 11x9 15x13 17x18 ;rleg 4
line 10x9 6x13 4x18 ;lleg 4
]
]
limbo: copy []
extend system/view/VID/styles [
fly: [
template: [
type: 'base
size: 20x20
draw: copy fly-shape
rate: 10
extra: copy [dir: 0 speed: 0 set: #[false]]
actors: [
on-created: func [face][
newdata face
publish face
]
on-time: func [face][new-pos/announce face]
]
]
]
spider: [
template: [
type: 'base
size: 20x20
draw: copy spider-shape
rate: 10
extra: copy [dir: 0 speed: 3 set: #[false]]
actors: [
sp: dir: speed: rp: sp*: df: ang: sd: rdir: rspeed: rd: ts: tr: rdf: rd*: none
on-created: func [face][newdata face]
on-time: func [face][
; Spiders center
rp: face/offset + 10
; Fly's data not changed
if target [
either dir = bb/3 [
; Fly's center
sp*: target/offset + 10
; Distance and angle from spider to fly
df: sp* - rp
ang: arctangent2 df/y df/x
; Spider moving?
either face/extra/set [
; Turn spider in direction of moving
face/draw/2: an + 90
; Spider step (can be fractional)
face/offset: face/offset + either gotr > 1 [rd*][gotr * rd*]
terrain/draw/7: face/offset + 10
; Reduce steps to take
gotr: gotr - 1
; Should spider stop?
if any [within? aim face/offset 20x20 gotr <= 0][face/extra/set: no]
][
; Turn spider in direction of moving fly (unless it's eaten)
unless target/extra/set [face/draw/2: ang + 90]
]
; Caught it?
if all [target within? target/offset + 10 face/offset 20x20][
if caught: find face/parent/pane target [
;move caught limbo
target: target/rate: none
;target: none
remove/part bb 4
]
]
][; Fly changes course/speed
; Fly's data
set [sp dir speed] next bb
; Fly's step
sd: as-pair (speed * cosine dir) (speed * sine dir)
; Normal
rdir: dir + 90
rspeed: face/extra/speed
; Spider's step perpendicular to fly's line
rd: as-pair (rspeed * cosine rdir) (rspeed * sine rdir)
; Fly's steps to meeting point
ts: 1.0 * ((rd/x * (sp/y - rp/y)) - (rd/y * (sp/x - rp/x))) /
((sd/x * rd/y) - (sd/y * rd/x))
; Is point on fly's actual course?
if ts > 0 [
; Spider's steps to meeting point
tr: (sp/x + (sd/x * ts) - rp/x) / rd/x
; Correct direction if needed
if negative? tr [tr: absolute tr rd: negate rd]
; Can spider reach this point in time
if (td: ts - tr) >= 0 [ probe "Reachable"
; Is the point within box?
unless within? aim: sp + (ts * sd) 10x10 480x480 [prin "Not in box. td, ts, tr: " print [td ts tr]
; What's earliest point?
if 0 < td [
prin "New aim: " probe aim: sp + (ts - (td / 2) * sd)
]
]
; Is closest point within box?
either within? aim 10x10 480x480 [
; Course from spider's position to meeting point
rdf: aim - rp
; Its direction
an: arctangent2 rdf/y rdf/x
; Turn spider
face/draw/2: an
; Recalculate spider's step (in case angle is changed)
rd: as-pair (rspeed * cosine an) (rspeed * sine an)
; Spider's step recalculated (to get right direction)
rd*: rd
; Set spider moving
face/extra/set: true
; Record steps to move
gotr: tr; - 1
; Take first step
face/offset: face/offset + either gotr > 1 [rd*][gotr * rd*]
; If already reached
if face/offset = aim [face/extra/set: no]
terrain/draw/3: aim - 45;7: aim
terrain/draw/7: rp
terrain/draw/8: aim
][probe "Still not in box"]
]
]
]
]
if not any [target empty? bb][
set [target sp dir speed] bb
]
]
]
]
]
]
view [
size 500x500
backdrop white
on-down [insert at face/pane 2 layout/only [fly]]
; Box for markers, web
at 0x0 terrain: box 500x500 draw [image web -100x-100 pen gray line 0x0 0x0];[circle -10x-10 2 pen red circle -10x-10 4]
fly
spider
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment