오픈 소스 모험: 에피소드 25: Imba 2 Game of Life

5680 단어 javascriptimba
Imba 1 앱을 몇 개 더 Imba 2로 이식하고 싶습니다.

이것은 매우 간단하며 또 다른 Game of Life 프로그램입니다. 상당히 간단하지만 Imba 1 버전은 svg:g에서 상속된 구성 요소를 사용했고 웹 구성 요소가 아직 지원하지 않기 때문에 Imba 2는 이를 수행할 수 없으므로 약간 조정해야 합니다.

다음은 the original source codehere you can see the app in action 입니다.

Imba 1 앱.imba




let def countNeighbours(cells, x, y)
  let count = 0
  for i, cell of cells
    if !cell:state
      continue
    let dx = Math.abs(cell:x - x)
    let dy = Math.abs(cell:y - y)
    if Math.max(dx, dy) == 1
      count += 1
  return count

let def runStep(cells)
  let nextCells = []
  for i, cell of cells
    let n = countNeighbours(cells, cell:x, cell:y)
    let nextState = (n == 3 || (cell:state && n == 2))
    nextCells.push({x: cell:x, y: cell:y, state: nextState})
  return nextCells

tag CellTag < svg:g
  def onclick
    data:state = !data:state
    trigger("pause")

  def render
    let visualStartX = 20 * data:x + 1
    let visualStartY = 20 * data:y + 1

    <self>
      <svg:rect .alive=(data:state) .dead=(!data:state) x=visualStartX y=visualStartY height=18 width=18>

tag App
  def setup
    let sizex = 30
    let sizey = 30
    @cells = []
    for x in [0..sizex]
      for y in [0..sizey]
        @cells.push({ x: x, y: y, state: Math.random() < 0.2 })

  def step
    @cells = runStep(@cells)

  def mount
    setInterval(&,100) do
      if @playing
        step
      Imba.commit

  def play
    @playing = true

  def pause
    @playing = false

  def onpause
    pause

  def render
    <self>
      <header>
        "Game of Life"
      <svg:svg>
        for cell in @cells
          <CellTag[cell]>
      <div.buttons>
        if @playing
          <button :click.pause>
            "Pause"
        else
          <button :click.step>
            "Step"
          <button :click.play>
            "Play"

Imba.mount <App>


임바 1 앱.scss




@import 'normalize-scss';
@include normalize();

.App {
  header {
    font-size: 64px;
    text-align: center;
  }

  svg {
    height: 600px;
    width: 600px;
    background-color: #aaa;
    margin: auto;
    display: block;
  }

  .dead {
    fill: #844;
  }

  .alive {
    fill: #3f3;
  }

  .buttons {
    text-align: center;
  }
  button {
    margin: 0.5em;
  }
}


Imba 2 앱.imba




def countNeighbours(cells, x, y)
  let count = 0
  for cell of cells
    if !cell.state
      continue
    let dx = Math.abs(cell.x - x)
    let dy = Math.abs(cell.y - y)
    if Math.max(dx, dy) == 1
      count += 1
  count

def runStep(cells)
  let nextCells = []
  for cell of cells
    let n = countNeighbours(cells, cell.x, cell.y)
    let nextState = (n == 3 || (cell.state && n == 2))
    nextCells.push({x: cell.x, y: cell.y, state: nextState})
  nextCells

tag cell
  prop data

  def onclick
    data.state = !data.state
    emit("pause")

  def render
    let visualStartX = 20 * data.x + 1
    let visualStartY = 20 * data.y + 1

    <self[left:{visualStartX}px top:{visualStartY}px] .alive=(data.state) .dead=(!data.state) @click.onclick>

  css
    position: absolute
    width: 18px
    height: 18px
    &.dead
      background-color: #864
    &.alive
      background-color: #3f3

tag app
  prop cells
  prop playing = true

  def setup
    let sizex = 30
    let sizey = 30
    cells = []
    for x in [0 ... sizex]
      for y in [0 ... sizey]
        cells.push({ x: x, y: y, state: Math.random() < 0.2 })

  def step
    cells = runStep(cells)

  def mount
    imba.setInterval(&,100) do
      if playing
        step()

  def play
    playing = true

  def pause
    playing = false

  def render
    <self>
      <header>
        "Game of Life"
      <div.board>
        for cell in cells
          <cell data=cell @pause.pause>
      <div.buttons>
        if playing
          <button @click.pause>
            "Pause"
        else
          <button @click.step>
            "Step"
          <button @click.play>
            "Play"

  css
    header
      font-size: 64px
      text-align: center
    .board
      position: relative
      height: 600px
      width: 600px
      background-color: #aaa
      margin: auto
    .buttons
      text-align: center
    button
      margin: 0.5em

imba.mount <app>


여기서 주요 문제는 SVG를 직접 사용할 수 없다는 것입니다. 우리는 각각 <svg> 하나가 있는 아주 작은 <rect> s를 만들 수 있지만 그 시점에서 구성 요소에 <div>s를 사용하고 구성 요소에 position: absolute를 사용할 수도 있습니다.

몇 가지 사소한 것:
  • 이벤트 모델이 변경되었으며 단순히 정의할 수 있는 것처럼 보이지 않습니다onX. 이러한 모든 이벤트를 수동으로 바인딩해야 합니다
  • .
  • for Imba 1에서 구문이 변경됨

  • 소스 코드



    소스 코드는 imba2-game-of-life repository에 있습니다.

    할 수도 있습니다see the live version here.

    다음에 온다



    우리가 너무 화려하게 한 것은 아니지만 지금이 그만 두기에 좋은 때라고 생각합니다. 다음 에피소드에서는 Imba 2에 대한 몇 가지 생각을 전하겠습니다.

    좋은 웹페이지 즐겨찾기