►
From YouTube: Rust Auckland - Azriel: ECS: A Programming Paradigm
Description
Rust Auckland meetup on 2018-12-04.
https://www.meetup.com/rust-akl/events/256460634/
An introductory talk that compares the OO model with an Entity Component Systems model of data storage and logic organization.
By Azriel
A
Cool
I
think
we're
recording
so
hi
guys
welcome
to
the
Russ
meetup
for
3rd
of
December,
4th
of
December
to
the
18
today,
I'll
be
talking
about
EC
as
a
programming
paradigm,
which
is
a
different
model
of
storing
your
data,
and
you
know,
organizing
your
logic
compared
to
say,
object-oriented
programming,
so
how
this
is
gonna
work,
I'm,
just
a
number
of
slides
as
87
there's
a
lot,
but
in
between
sections
I'll
have
some
breather
slides
for
some
questions
about
that
section
that
we
just
passed.
A
So
if
you
feel
like
something's,
going
too
fast
will
will
slow
down
as
well
cool
so
but
myself,
I
used
to
work
in
other
beta,
matrix,
distributed
system
management
and
now
I'm
making
a
rest
game
alright.
So
what
we're
going
to
go
through
today
and
we're
going
to
go
through
and
the
data
organization?
We
will
compare
oo
and
PC,
which
is
entity
component,
we'll
look
at
how
that's
applied
in
the
game
scenario.
A
A
So
if
you
have
a
struct
or
class,
your
fields
are
going
to
be
either
primitives
or
richer
types,
and
if
you
have
richer
types,
they're
going
to
be
your
own
structs,
which
further
have
your
own
fields
as
well,
and
so
over
here
you
can
see.
In
this
example,
we've
got
a
person
at
the
top
level.
The
person
has
two
fields:
contact
detail,
date
of
birth
and
each
of
those
have
their
own
fields,
down
the
line
so
I'm
in
code.
A
That
looks
something
like
this
kind
of
trivial
and
if
you
have
multiple
people,
you
might
start
them
in
the
well
like
this,
so
you
have
a
vector
of
person.
So
we
tend
to
call
this.
The
array
of
structs,
so
the
vector
is
kind.
The
array,
because
it's
generally
backed
by
an
array
and
the
person
is
a
struct,
and
so
we
tend
to
call
this
pattern
array
of
structs
in
preparation
for
the
next
pattern,
where
we
are
going
to
change
that
into
a
struct
of
arrays,
so
destructive
arrays.
A
All
right
so
so
remember
how
we
had
a
person
with
two
fields,
so
one
of
them
was
contact
details.
The
second
was
date
of
birth,
so
we're
going
to
have
now
two
vectors
one.
That's
going
to
start
all
of
the
contact
details
and
the
second
one's
going
to
start
off
all
of
the
date
of
birth.
So
here
and
we
like
to
call
each
field
a
component
because
that's
one
part
of
the
person
and
to
make
sure
our
data
is
consistent,
each
person
is
represented
by
one
index
across
both
vectors.
A
So
that
way,
if
we
look
at
it
in
pictorial
form
index
say
one:
if
you
go
to
the
contact
details
of
index,
one
plus
the
date
of
birth
index,
one
that's
enough
data
to
reconstruct
the
person,
so
the
person,
class
or
struct
no
longer
exists.
It's
a
map
concept,
so
some
people
might
think
like.
Why
would
anyone
want
to
do
that?
It's
like
asking
the
question:
why
would
anyone
want
to
build
a
relational
databases
and
that's
not
a
joke,
because
this
is
actually
the
really
relational
model
and
we
will
see
how
we
do
joints
later.
A
Now,
if
we
had
our
present
struct
and
it
start
in
the
world,
we
didn't
really
need
the
world
record
right
now,
but
you
may
have
a
vector
of
person
and
the
code
to
calculate
that
is
to
iterate
over
each
of
the
people,
some
reference
age
and
divide
by
the
number
of
people
so
in
memory.
This
is
the
data
that
we
iterate
over.
A
So
the
you
can
see
here
on
the
Left
p,
0,
1,
2
3,
those
represent
different
instances
of
a
person
and
the
cells
on
the
right
represent
the
data
that
you
fetch
for
each
person
for
calculating
the
average
age.
We
only
need
the
date
of
birth
because
you
need
now
date
of
birth,
and
then
that
gives
you
your
age
now.
If
we
do
this,
if
you
do
the
same
thing
with
the
struct
of
arrays
approach,
we
are
going
to
remember.
Look
the
person
in
two
bits.
A
A
Now,
if
you
look
at
the
data
that
we
iterate
over,
it's,
as
you
can
see,
just
a
little
purse
and
the
data
that
we
need
is
just
the
data
purse
which,
like.
Why
should
I
care
about
this
because,
like
usually
computers,
are
fast
enough
right.
So
this
is
actually
one
of
the
important
questions
when
you
consider
should
you
go
with
easy,
theta
layouts,
because
if
you're,
not
in
a
performance
constraint,
environment,
sometimes
having
the
old
layout,
is
actually
better
for
us
a
development
effort.
A
So
if
we
consider
the
locality,
when
you
tell
your
computer
I,
want
to
access
this
element
in
this
array,
and
your
computer
thinks
maybe
I
should
fetch
some
R,
because
if
you're
accessing
array
index
0
computer
is
going
to
have
some
optimizations
and
thinking
oh
you're
likely
going
to
be
accessing
the
elements
next
to
it.
So
it's
going
to
fetch
a
whole
chunk
of
B
right
into
your
cage,
because
cache
access
is
much
faster
than
memory
access.
It's
like
maybe
8
cycles
compared
to
100
cycles
yeah.
A
So,
let's
look
at
how
that
fits,
and
so
am
the
hierarchical
model.
So
a
model
if
you've
got
bigger
elements
you're
going
to
fit
fewer
elements
into
your
cage,
whereas
if
you've
got
smaller
elements,
destructive
destruct
of
arrays
approach,
you're
going
to
be
able
to
fit
more
of
those
into
your
cache
and
therefore
you
will
get
more
cache
hits
and
fewer
acacia
misses
and
that
can
shave
off
quite
a
bit
of
time.
A
Yeah
you're
going
to
have
more
than
4
5
&
10,
because
this
is
just
representational
all
right
so
to
see
the
effects
of
this
I
did
a
benchmark
and
we
can
open
it
and
we
won't
actually
run
it
today,
but
to
get
the
real
stats
I
had
to
increase
contact,
detail,
sighs
whoops!
You
can
see
that,
but
I
do
make
contact
details
really
big
before
you
could
actually
have
a
consistent
result.
A
So
to
get
the
array
of
structs
actually
having
enough
slowdown
to
be
comparable,
and
so,
if
you
want
to
is
look
at
the
code
for
that
grass
cargo
we
just
rested
built
tool
provides
them
a
good
way
of
benchmarking,
your
code,
and
so
the
code
for
this
is
available.
Online
yeah
I
ran
this
lots
of
time,
so
just
make
sure
that
you
could
see
that
there
is
a
definite
advantage
for
cash
in
terms
of
data
locality
when
you
use
destructive
arrays
approach.
A
B
B
A
A
A
D
A
A
Okay,
what
was
I
thinking
yeah
there
we
go
okay,
so
I'm
we're
going
to
look
at
how
we
might
use
ECS
in
a
game.
So
if
we
think
of
oh,
is
this
disclaimer
so
and
the
examples
here
are
based
on
the
specs
crate,
which
is
an
implementation
of
ecs
in
rust.
There
are
other
implementations,
like
unity.
Has
its
own
I,
believe
yeah
cool.
A
So
in
a
game
scenario,
perhaps
you
have
these
four
types:
a
player
is
renderable
and
you
can
draw
the
player
it's
about
position
in
the
game
and
it
can
move
around
velocity
and
it
takes
input
which
is
perhaps
user
controlled
monster
is
similar.
It
doesn't
have
take
controls,
speech
bubble.
You
can
draw
it
on
screen,
but
perhaps
you
can
only
press
next,
so
it
doesn't
need
to
have
a
and
the
map
is
special.
It's
got
some
something.
A
On
balance,
perhaps
to
prevent
your
characters
and
monsters
from
walking
off
screen,
okay,
so
in
the
object
oriented
model
generally,
you
want
to
compare
good
object-oriented
design
with
ECS
good
ECS
design.
You
don't
want
to
compare
the
object-oriented
programming
syntax
with
C,
yes,
because
people
tend
to
compare
like
this
design
is
bad.
Let's
compare
it
to
a
good
ECS
design.
That's
not
really
comparing
two
good
things
with
each
other
and
also
am
visible
appoints.
Even
though
I
say
these
two
are
under
the
good
design.
A
So
the
problems
that
you
can
get
when
you
are
using
the
object
oriented
model.
If
you,
if
you
think
of
having
some
renderable
interface,
you
share
common
logic.
It's
like
common
renderable
logic
for
different
types.
You
need
to
wire
those
different
types
through
as
renderable
to
the
thing
that
render
stuff
so
that
wiring
code
is,
you
have
to
write
it
for
each
type
that
you
implement.
A
So
even
though
I'm
you
well,
when
you
implement
a
trait
like
renderable
for
a
certain
type,
you
have
to
do
that
for
whether
or
not
you're,
using
up
your
XLR
ECS
style,
but
even
after
you've
done
that
in
the
old
style.
You
need
to
also
wire
that,
through
to
the
logic
that
will
consume
it
in
the
ec
style,
you
don't
have
to
we'll
see
that
later
and
other
problems
well
more
like
work.
A
I
guess
you
can
say
for
borrowing
parts
of
an
object
to
process
things
in
parallel,
it's
much
harder
in
an
object-oriented
style,
because
if
you
want
to
use
the
same
data
across
different
systems
or
different
logic,
you
need
to
either
have
immutable
references
which
you
share
across
each
of
those
update
functions.
Are
you
will
have
to
say
copy
and
clone
each
of
the
fields
so
that
they
don't
end
up
with
having
Barrow
errors?
And
you
can
look
at
them.
So
viewers
practice,
one
of
the
interesting
ones.
A
I
only
came
across
like
about
a
month
ago,
and
it's
pretty
much
having
a
layer,
a
layered
strapped
on
top
of
your
normal
struct
and
having
immutable
references
to
the
underlying
fields
and
that
way
it's
easier
to
pass
around.
We
can
look
at
that
in
perhaps
after
after
the
talk,
okay,
so
in
the
entity
component
model,
and
we
know
that
some
components
apply
to
some
entities
so
player.
A
The
type
every
instance
of
the
player
type
will
have
renderable
opposition
velocity
and
input,
but
if
we
are
going
to
star
each
of
these
components
in
a
common
vector,
we
know
that
across
different
types,
you're
not
going
to
have
all
of
those
components
which
means
your
vectors
to
make
sure
your
vertical
slice
is
still
consistent
for
an
object.
You
need
to
have
empty
spots
inside
those
vectors
and
the
way
we
can
do
that
is.
We
can
have
vectors
with
option
of
the
component
type
right,
yeah
we'll
get
to
how
we
solve
these
problems.
A
Okay,
so
and
to
know
which
index
is
a
player
which
index
is
a
monster.
You
can
keep
track
of
those
in
the
indices
in
separate
locations.
A
Okay,
so
the
problem
that
you
can
see
is
probably
more
like
problems.
You
can
see
right
so
there's
a
lot
of
empty
spots
inside
those
vectors
and
so
and
that's
usually,
usually
you
get
memory,
bloat
and
so
other
problems.
You
can
also
hit
our
entity
creation.
So,
every
time
you
want
to
create
the
entity,
you
need
to
know
where
to
put
it
inside
all
of
those
vectors,
and
so
you
can
keep
track
of.
They
use
a
Clif
Bar.
But
if
you
always
increment,
you
will
eventually
run
out
and
deletion
as
well.
A
So
if
you
want
to
delete
an
entity
somewhere
earlier
in
the
vectors,
do
you
well
shifting
everything
back?
It's
not
a
good
idea,
because
when
you
oh
well,
you
need
you
need
mutable
access
for
all
of
those
component
vectors
and
then
you
eventually
shift
all
of
the
memory
back,
but
that's
not
great
alright.
So
you
can
see
this
is
quite
problematic
and
also,
if
someone's
referencing,
a
particular
entity,
say
an
index,
they
get
they're
just
holding
an
index
for
some
reason.
A
So
do
we
have
any
questions
before
we
look
at
how
we
solve
ease.
A
D
A
So
we
are
accessing
them
through
through
and
through
a
pointer
file,
pointer
yeah,
but
in
terms
of
components,
the
entity
component
cell-
you
don't
have
to
because
the
components
are
start
in
its
own
vector.
So
our
storage,
it's
not
necessarily
a
vector,
but
because
they
are
concrete
types.
You
don't
have
that
overhead.
A
So
generational
arena,
so
some
of
you
think
arena
the
Coliseum,
but
it's
not
like
that.
So
generational
arena,
it's
a
pattern
in
computer
science,
where
the
arena
is
a
chunk
of
memory
that
you
request
from
the
computer
and
you
manage
it
yourself.
So,
instead
of
requesting
bits
of
memory,
I
need
this
memory.
For
now
and
after
you
use
it,
the
computer
freeze
it.
A
What
you
do
is
you
press
a
huge
chunk
of
memory
and
you
hold
on
to
the
whole
thing
and
what
you
can
use
and
free,
well
use
and
unused
bits
of
that
memory
without
actually
free
Myint,
and
so
this
way
you
can
save
some
memory
allocation
time
and
the
generational
part
of
this
is
we
use
something
called
a
generational
index
to
track
where
we've
got
free
space
inside
that
chunk
of
memory.
So
in
this
example,
we
are
looking
at
the
generational,
arenak
rate.
I.
A
Think
specs
has
something
similar,
if
not
exactly
the
same,
but
if
we
look
at
what
a
generational
index
is,
so
if
you
index
a
vector
normally,
you
just
have
0
to
n
minus
1.
The
index
is
your
size
in
a
generational
arena.
You've
got
a
second
part
of
it
called
D
generation,
and
the
generation
is
something
which
we
indicate.
A
When
was
this
item
put
into
that
memory
space
and
when
we
retrieve
it,
we
must
point
to
not
just
the
index
so
the
position
in
the
check
of
memory,
but
also
the
generation
that
we
expect
the
item
to
be
so
that
way
we
can,
if
we
reuse
a
slot
and
we
increment.
So
if
we
reuse
a
slot,
we're
going
to
insert
a
different
item
and
we're
going
to
use
a
different
generation.
A
So
if
anyone
access
the
same
slot
with
an
older
generation,
we're
going
to
say
no,
there's
nothing
here,
we'll
see
that
in
pictorial
form
as
well,
so
the
key
concepts
for
a
generational
arena.
You
keep
a
pool
of
memory.
In
this
example,
we
have
a
vector
and
we
remember
which
slots
are
empty.
A
We'll
see
that
as
well
and
every
time
you
free
a
slot
you're
going
to
keep
track
of
what
generation
that
you,
what
generation
that
slot
contained
and
you're
going
to
increment
a
counter
to
make
sure
it's
at
least
one
more
than
the
slot
that
you
freed.
We
will
see
this
in
example,
so
perhaps
we
will
skip
this
slide.
I
just
mentioned
it
okay,
so
we
keep
a
vector
here
and
each
slot
will
contain
an
inner
variant
so
occupied
or
free.
And
if
it's
occupied,
you
start
degeneration
of
the
item
that
you
inserted.
A
Now
when
we
delete
an
element,
so
everything's
inserted
with
generation
0,
because
here
is
generation
0
when
we
delete
an
element
at
say
index
1,
we're
going
to
me
know
that
index
1
is
going
to
be
deleted.
So
when
we
delete
we're
going
to
track
1
as
the
next
free
slot
to
insert
any
new
data
that
comes
in
and
when
we
deleted
it,
we
knew
that
that
was
free.
So
we're
going
to
update
1
to
be
a
free
slot
and
point
it
at
4
and
at
the
same
time,
the
generation
that
we
deleted.
A
The
element
at
was
0,
so
we
track
the
next
time
we
inserted
a
an
element
into
any
slot.
It
must
be
generation
1.
So
what
this
does?
It
means
that
if
we
delete
any
other
slot
which
is
occupied
because
they
are
all
generation
zero,
we
can
safely
insert
new
data
into
those
free
slots
with
generation
1
and
when
anyone
queries
with
generation
0,
it's
going
to
say
no,
there's
nothing
at
that
and
that's
what
we're
as
if
they
did
query
something
which
didn't
exist
with
generation
0.
A
A
A
Generation
arena
which
tracks,
if
I,
want
to
insert
something
at
if
I'm,
to
insert
new
data.
It
knows
that
slot
1,
which
was
previously
use,
can
be
reused,
who
just
inserted
with
a
newer
generation.
So
we
never
have
to
really
keep
growing
and
incrementing
our
index
and
I'm
gonna
increment
our
index.
When
there's
no
more
free
slots
beforehand
and
for
entity
deletion.
A
We
can
solve
the
part
where,
if
someone's
holding
a
reference-
and
it's
still,
we
can
track
that,
because
if
we
do
not
have
this
generation
there
and
they
requested
something
at
index
one
and
there
was
new
data
at
index,
one.
We
returned
them
that
new
data
and
they
wouldn't
know
that
it's
invalid.
So
at
least
you
can
solve
that
problem
and
I
think
we'll
go
through
one
more
yeah,
which
will
look
at
how
we
solve
the
memory.
Bloat
problem,
so
I'm
here,
Oh
II
see
entity
component
Sarge's.
A
So
if
we
use
a
vector
to
back
every
single
component
and
that
we
start
it
can
be
a
waste
of
memory.
So
in
this
example-
and
you
can
see
that
for
render
bruh
for
renderable
it's
okay,
because
we're
using
every
single
slot
in
the
vector
but
say
for
positions
and
so
and
so
forth,
there
are
empty
spaces.
A
And
so,
if
you've
only
got
a
few
entities
which
have
this
component,
it's
going
to
have
a
lot
of
empty
spaces
and
say
if
you
have
a
thousand
entities,
you're
gonna
have
like
a
thousand
capacity
vector
for
every
single
vector
for
every
single
component,
and
that's
that's
quite
wasteful.
So
in
specs
there
are
a
variety
of
different
storages,
so
effects
storage.
I'm
we
went
through
em,
it's
it
makes
sense
for
components
where
almost
every
entity
has
that
component.
A
A
So
if
you
only
have
say
two
components
sentence,
sorry
two
entities
that
have
these
components
you're
only
going
to
have
a
mess,
a
data
table,
a
data
vector
which
has
those
two
elements
and
the
lookup
table,
which
is
still
sparse,
will
point
to
the
dense
table.
Oh
sorry,
dude
inspector,
another
one
is
hash
map
storage.
So
if
you've
got
like
a
thousand
entities,
only
one
of
them
has
this
component.
A
A
Okay,
so
this
different
types
of
storages
they
solve
the
memory
block
problem
and
you
can
have
your
own
implementations
such
as,
like
null
storage,
is
something
which
you
can
tag
an
entity
with,
and
it
doesn't
actually
store
any
data
for
the
entity.
But
when
you
request
so
I
think
it's
like
a
boolean
search
and
when
you
request
a
that
component
for
the
entity,
the
storage
is
just
going
to
return.
A
B
B
A
So
hope
I
think
not
take
away
discussing
correctly
and
then
the
answer
so,
if
I
understand
the
question
correctly,
is
that
because
you've
got
a
lookup
table
as
well
as
the
actual
component
vector
you
have
to
scan
both
before
you
can
access
B?
A
A
So
if
you
do
have
a
lookup
table,
you're
going
to
its
fast
to
look
up
what
components
are
in
the
sorry,
if
you
have
a
look
at
table
and
you
have
an
entity
index,
it's
fast
to
check
if
that
entity
has
that
component
and
if
you
want
all
entities
that
do
have
that
component,
you
do
need
to
go
through
every
index
and
find
out
if
they
have
the
like,
say
the
data
breath
and
I
guess
in
practice
it
comes
down
to
is
it?
A
A
A
Though
I
have
not
gone
to
the
level
before
in
specs,
but
I
do
know,
they
provide
I
think
it's
usually
unsafe
line
in
there
yeah
so
yeah
you
can
you
try
so
yeah.
F
A
Countess
global
to
best
serve
that
time.
You
don't
overflow
the
generation
easily
so
say
if
you
always
use
the
first
four
slots,
but
you
never
really
go
over
five
entities
bit
strange,
but
the
generation,
actually
the
generation
will
increment
faster.
That
way,
because
every
time
you
delete
you're
going
to
increment
the
generation
for
our
particular
that's
right
for
everything.
So
if
you
delete
generation
0
from
slot
zero
too
far,
you're
going
to
only
have
generation
1
next,
because
all
of
those
firsts
all
of
those
are
generally
had
generation
0.
A
D
D
D
A
Okay,
we
shall
go
on
hey.
We
have
20
minutes
and
we
have
got
about
one
page
left.
Okay,
so
the
logic
part.
So
a
logic
is
how
we
deal
with
our
data
transformations.
So
let's
say
we
have
a
task.
We
want
to
update
positions
for
anything
with
positions
and
velocities
based
on
deep.
So
sorry,
if
we
have
anything
with
a
position
and
the
velocity,
we
want
to
update
the
position
based
on
the
velocity.
So
it's
pretty
much
this
position,
clásicos
velocity,
really
simple
right.
A
The
update
function
inside
the
class
hiding
the
code
means
better
encapsulation,
that's
what
we
heard
from
every
CS
cars.
That's
not
what
they
said
right.
My
lecturers
out
right
in
front
of
me,
yeah,
so
Oh
P,
yes,
okay,
are
there
programming
syntax?
So,
even
if
you
use
interface
inheritance
and,
for
example,
here
position
update
is
a
trait
if
you
duplicate
the
logic
across
two
different
types:
you're
going
to
be
increasing
software
maintenance
costs,
because
if
you
say
you
have
100
types,
you're
actually
doing
the
same
thing
in
hundred
places.
A
A
Alright,
let's
make
a
big
so
a
bit
smaller
yep,
so
dragon
I
can
drag
that
I,
don't
know
if
you
can
open
it,
a
few
close
it
alright,
so
we've
got
our
player
type
and
our
monster
type
and
they
both
positionable
and
moveable
time,
can
see
here,
position
ball,
movable
and
if
you
are
moveable,
we
get
your.
We
borrow
your
velocity
immutably
and
we
will.
If
you
are
positionable,
we
will
borrow
your
position,
mutiply
cool,
all
right.
A
So
if
we
run
this,
you
will
actually
get
so
this
a
big
function
will
go
through
all
of
these
things,
which
are
both
positionable
and
movable.
I
lost
my
game,
object
straight
yeah,
so
accurate
game
object,
some
position,
ball
and
movable,
and
so,
when
we
run
this,
it's
going
to
go
through
all
of
the
objects
which
are
both
positionable
and
movable
borrowing,
your
velocity,
you
reference
it
to
get
the
underlying
type
and
try
to
update
the
position
and
you're
going
to
see
an
error
saying:
you're,
borrowing,
the
game,
object,
immutably
and
then
you're
trained.
A
You
borrow
it
immutably
again
like
immediately
line
after
no
interesting
thing
is,
if
I
grab
that
and
put
it
down
here
and
run
exactly
the
same
code,
it's
happy
right
custom.
So
if
you
look
at
the
output,
the
player
position,
zero
velocity
one
monster
tend
and
negative
one
in
increments
the
position
of
the
player
by
one
and
decrements
the
position
of
the
monster.
So
over
here
you
can
see
that
even
in
a
sequential
function,
you
can
already
get
quite
difficult,
well
obscure,
barring
problems
and
the
problem
that
you
will
hit.
A
If
you
try
to
parallelize
this
and
then
paralyzes
across,
like
multiple
systems,
you're
going
to
have
a
hard
time
say,
figuring
out
how
to
borrow
from
each
different
type
and
keep
them
running
in
parallel,
without
having
lots
of
overhead
like
wrapping
your
fields
in
mutex
and
that
kind
of
thing.
So
this
is
actually
good.
Object-Oriented
design,
you're,
not
you
are
not
duplicating
your
logic
anywhere
else,
but
you
do
need
to
wire
those
types
through
to
the
same
game
object,
and
then
you
can
get
the
benefits
of
no
duplication.
A
A
You
have
to
figure
out
how
to
borrow
our
own,
your
data
that
you
have
mutating
and
that's
quite
difficult
if
you
go
with
the
OO
design,
so
well,
one
of
the
things
you
could
do,
which
is
probably
not
a
good
idea,
is
to
deconstruct
your
objects
and
pass
them
to
your
different
updating
functions
and
then
reconstruct
them
back
later
and
then
figure
out
the
priorities
of
that
right.
So
that's
also
going
to
be
a
like
hairy
problem.
A
Okay,
so
we're
going
to
look
at
how
we
do
this
in
the
VCS
style.
So
systems
are
the
s
in
yes
and
we're
going
to
look
at
pictures
so
pictures
given
a
lock
or
a
door
and
the
door
lock
has
like
two
buttons
position
and
velocity.
That's
what
the
two
green
things
are
this
wrong
button.
So
this
key
the
entity
will
turn
this
lock
if
it
has
the
right
teeth,
both
the
position
and
velocity
teeth.
A
So
it
does
that
the
components
this
key
with
an
extra
tooth
will
also
open
this
lock
because
it's
still
pressing
the
right
green
buttons.
But
this
key
will
not.
As
in
we,
we
are
missing
a
tooth.
We
don't
have
velocity
so
something
with
position,
but
no
velocity
the
systems
not
gonna,
run
on
that,
and
we
can
also
do
something
else.
A
So
if
we
have
a
lock
with
a
red
button
for
velocity
it
once
he
wants
to
run
over
all
entities
with
a
position
but
not
velocity
so
kind
of
like
you
are
we're
not
like
this
in
sequel
end,
so
so
that
broken
key
will
work
here,
but
the
working
key
will
not
work
right
so
and
that's
a
little
analogy.
So
the
system
is
the
lock
the
key
well,
the
entities
is
aren't
just
your
IDs
and
then
position
and
velocity.
Those
are
your
components.
So
when
we
look
at
this
in
code,
let's
remember
this
picture.
A
So
players
have
these
four
components:
monsters
of
three
and
so
and
so
forth.
If
we
go
over
our
storages
and
join
them,
we
will
get
an
iterator
over
the
entities,
know.
A
A
A
That's
so
that's
how
specs
implemented
it
I'm,
not
sure
if
all
other
crates
haven't
right.
Okay,
so
this
is
just
the
comparison.
So
we
had
this
in
the
object-oriented
style
and
we
have
this
in
the
system
style
which
they
look
very
similar
right.
So
so
you,
if
you
have
good
design,
usually
you'll,
have
it's
easy
to
translate
into
the
easy,
sell?
E
A
A
Believe
so
you
do
have
your
dependencies
like
you're
some
functions
mess
around
before
the
others
and
that's
what
you
this
is
how
we
will
see
a
T
next
and
also
what
those
functions.
Do
you
I
think
you
would
generally
design
both
your
data
like
the
how
you'd
break
your
data
apart
with
the
way
you
want
to
be
transform
the
data
or
operate
over
the
data,
so
I
think
the
general
advice
is
to
keep
your
components
small.
So
you
get
that
data
locality
benefits,
though,
if
you
think
about
it.
A
A
A
Okay,
so
how
it
looks
like
as
a
whole.
So
we've
got
your
system
data
up
here
and
it's
just
got
one
well,
it's
got
multiple
functions,
but
this
is
the
only
one
that
you
really
always
have
to
implement.
A
There's
other
trade
functions
which
let
you
set
up
the
system.
If
you
look
into
the
details
of
that,
it
lets
you
initialize
some
things
and
there's
also
another
function
which
they
don't
really
advertise,
but
it
lets
you
give
a
hint
to
the
dispatcher,
which
is
a
thing
that
runs
the
system's,
how
long
the
system
might
generally
take
to
run
so,
whether
it's
average
long
or
short,
and
that
way
it
can
end
up
feeling
a
little
bit
better
okay.
A
So
if
we
go
to
the
next
one,
this
is
the
dispatcher,
which
is
the
layer
above
the
systems.
So
each
system
does
one
particular
data
transformation,
or
maybe
it
displays
through
the
screen.
So
the
dispatcher
is
the
thing
which
orders
those
systems,
so
it
it
retain.
It
keeps
in
it
keeps
track
of
what
systems,
depending
which
other
ones
and
how
many
workers
there
are,
and
also
when
I,
should
execute
particular
systems.
So
in
picture
farm,
it's
something
like
this
and
this
whole
box.
This
big
wider
box
is
our
system
graph
and
meda
touch.
A
Note,
oh
I
mean
we
know
it's
without
an
incoming
edge
are
able
to
be
run
at
the
start
or
any
time
they
want.
But-
and
we
know
it's
with
edges,
they
must
run
in
that
order
and
if
you
have,
if
you
have
any
two
systems
which
can
run
at
the
same
time,
you've,
you
first
need
to
make
sure
that
they
are
not
having
any
data
dependencies
like
mutable
and
immutable
access.
At
the
same
time
before
you
run
them
so
yeah,
each
node
sorry
is
a
system.
A
I
did
not
mention,
so
this
system
has
completely
run
before
you
can
run
the
others,
and
each
time
you
tell
the
assistant
tell
the
dispatcher
to
execute
it's
going
to
run
all
of
these
systems
once
so.
It's
pretty
much
a
task
flow
graph,
okay,
so
I'm
in
in
terms
of
games.
You
want
to
get
all
of
this
the
whole
system
graph
to
executed
within
either
16
or
33
milliseconds,
because
that's
what
yeah
well
60
FPS
at
30
fps
you
get
yeah
and
I.
A
Guess
if
you
think
of
that
casing
thing
we
had
earlier,
if
you
can
shave
off
like
one
millisecond,
it's
going
to
give
you
one
1/16
of
your
whole
or
in
your
whole
processing
time
to
play
with
okay
yeah.
There's
a
link
down
here
to
see
how
you
set
this
up,
not
exactly
this
but
I'm
a
system
crash
and
the
thread
pool
is
the
full
of
worker
threads
and
we
use
we
use
rayon,
which
I
think
defaults
to
one
thread
per
car
on
your
finger,
cool,
so
I
think
that's
our
summary
yep.
A
A
The
logical
partitioning
in
Olin
is
by
object
state.
So
if
you
want
to
know
what
a
player
is,
you
can
easily
open
the
player
type
and
you
can
see
all
of
the
fields
it's
got
and
hierarchically
all
the
way
down
in
ec.
You
can't
see
that
you
have
Sarge's
and
you
need
to
like
look
at
each
storage
and
you
can
actually
get
invalid
state
like
if
someone
just
randomly
inserts
a
component
into
an
index
where
it's
meant
to
be
a
player,
you
don't
get
sick.
A
Okay,
you
don't
get
that
safety,
whereas
in
all-
and
you
can't
do
that-
because
it's
compilation
error,
but
in
terms
of
the
logical
partitioning,
the
behavior
of
anything
in
an
entity
component
system,
so
anything
with
certain
components
will
always
inherit
the
behavior
that
those
components
should
have.
That's
a
really
strange
statement
about
them.
I
try
again,
so
anything
with
two
particle
components
are
any
number
of
practical
components
which
should
have
certain
behavior
will
have
it
because
the
system
doesn't
choose
based
on
type
yeah.
So
you
got
a
visible
concrete
model
in
object-oriented
land.
A
A
At
the
same
time,
so
I
think
unity
has
and
that
kind
of
thing
with
the
seashell
compiler.
So
you
can
get
Kish
optimized
code
like
native
code.
If
you
have
a
really
big
compiler
rust
does
auto
vectorize,
but
I
heard
from
someone
that
it
doesn't
do
it
so
well
for
floats
and
Barrel
checker
management,
any
component
model
kind
of
Windsor,
so
I
think
that's
all
ahead.
H
A
Finding
it
so
I'm
reading
it
came
in
rest
and
so
I'm
using
the
amethyst
game
engine
which
backs
into
specs
and
it's
well
one
thing:
it
was
a
lot
easier
to
do:
dependency
management
in
Russells,
yes,
switching
from
Weber
language
I
was
using.
Let
me
guess:
I
was
using
to
to
rest
and
saves
me
a
lot
in
terms
of
the
fluff
around
the
game
right.
So
that's
a
big
bonus.
It's
so
using
spec,
so
ACS,
it's
not
too
difficult.
A
I
did
have
to
do
a
big
refactoring
off
like
oo
South
co2,
easy
Sal
code
and
that
works
really
well.
If
you
are
working
alone,
s
and
I
did
a
lot
of
Find
and
Replace
which,
like
I,
can
change
55
seconds
being
fearless
because
of
rest
compiler
and
as
well
as
adhering
to
conventions,
because
if
you
have
multiple
developers,
you
cannot
guarantee
that
you
aren't
going
to
adhere
to
the
same
conventions
and
he's
so
using
fun
and
replace
it's
not
going
to
be
a
it's,
not
always
a
good
thing.
A
Yeah
we've
all
did
this
I
guess.
H
H
Like
seeing
you
a
types,
I
guess
is
that
just
a
read
right.
A
So
so
excess
resources,
so
first
I'll
answer
the
the
resource
pack.
So
resource
is
pretty
much
like
a
global
variable
thing
and
you
check
that
into
the
world
as
well.
So
you
don't
just
assume
done
only
have
don't
always
have
to
work
over
components.
You
can
also
work
over
resources
which
are
just
any
type
that
you
put
into
the
world
like,
like
maybe
a
drink.
You
pass
information
from
one
system
to
another
which
is
not
through
a
game
object.
You
might
want
to
say
alright.
A
The
games
passed
in
one
system,
like
maybe
an
input
system,
will
say:
hey
I
received
this
key
like
P
or
whoever
it
key
is
for
pass,
and
then
the
other
systems
really
will
read
the
pause
state
and
decide
to
not
run
that
kind
of
thing.
So
it's
just
a
readwrite
luck.
Resources
are
not
retried
lux,
but
then
the
wrap
around
it.
The
read
and
write
those
generic
types.
Those
are
the
I
think
they've
got
the
luck
inside
them.
A
D
F
A
So
it
went
through
a
few
generations,
so
the
doors,
the
Java
version.
There's
the
update
Java
version.
There
was
the
C++
version.
One
two
three
like
I
went
through
like
before:
I
knew
before
I
knew
oriented
programming,
so
I
started
writing
this
game
in
high
school,
actually,
which
is
a
long
time
ago,
then
I
learned
about
design
patterns.
That's
the
OL
part
I
switched
to
C,
plus
plus,
because
I
could
not.
Oh
one
of
the
artists
could
not
run
the
Java
version
on
the
computer.
Excuse
well,
then.
A
Well,
when
I
went
to
see
first
us
dependence,
dependency
management
was
an
issue.
It's
for
still
an
issue
so
I
had
I
tried
out
the
maven
plug-in.
Then
I
tried
out
B
code,
which
was
it's
is
that
now,
but
then
they
it
was
superseded
by
Conan,
Conan
IO
and
that's
maintained
by
one
factory
now,
I
think
j-rock
yeah
so
and
that's
a
Python
tool
too,
of
make
life
easier
for
dependency
management
in
synchronous.
A
But
I
switch
to
rest
because
I
had
too
many
rewrites
in
C++,
LAN
and
I
did
fight
sick
faults,
which
were
hard
to
fight
because
you
don't
know
whether
yeah
go
ahead
like
Heisenberg
right
when
you
compile
in
debug
mode
it
doesn't
show
up.
But
if,
when
you
compile
and
really
smell
it,
it
does,
and
it's
like
yeah.
C
Yes,
yes,
sir,
alright
so
I
think
we'll
do
pizza
now
and
for
those
of
you
that
I
came
to
stay
and
potentially
just
do
a
bit
of
we
go
I
mean
I've
had
this
fishbowl
session,
but
then
we
might
just
have
a
bit
of
a
discussion
about
2019
and
you
know
what
people
are
looking
forward
to
it.
Actually
yeah
yeah.
If
people
share
some
of
the
knowledge
about,
you
know
what
is
coming
because
I'm
sure
people
that
are
like
bits
and
pieces
I
have
bits
and
pieces,
but
maybe
there's
something
that
sounds
like.