Skip welcome & menu and move to editor
Welcome to JS Bin
Load cached copy from
 
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  <div id="board"></div>
  <button id="gravityButtonRemove">Remove gravity</button>
  <button id="gravityButtonAdd">Add gravity</button>
  <br>
  <button id="redColorRemove">Remove red color</button>
  <button id="redColorAdd">Add red color</button>
</body>
</html>
 
const canvas = document.createElement("canvas")
canvas.width = canvas.height = 500
canvas.style.backgroundColor = "black"
const ctx = canvas.getContext("2d")
document.getElementById("board").appendChild(canvas)
// buttons
const gravityButtonRemove = document.getElementById("gravityButtonRemove")
const gravityButtonAdd = document.getElementById("gravityButtonAdd")
const redColorRemove = document.getElementById("redColorRemove")
const redColorAdd = document.getElementById("redColorAdd")
gravityButtonRemove.addEventListener("click", () => {
  ECS.removeComponentFromEntity(Box, "gravity")
})
gravityButtonAdd.addEventListener("click", () => {
  ECS.addComponentToEntity(Box, gravityComponent)
//   console.log(Box)
})
redColorRemove.addEventListener("click", () => {
  ECS.removeComponentFromEntity(Box, "redColor")
  console.log(Box)
})
redColorAdd.addEventListener("click", () => {
  ECS.addComponentToEntity(Box, redColorComponent)
  console.log(Box)
})
class EntityComponentSystem {
  constructor() {
    this.components = []
    this.processors = []
    this.entities = []
  }
  getProcessorNames() {
    return this.processors.map(processor => processor.name)
  }
  hasProcessor(processorName) {
    return this.processors.find(processor => processor.name === processorName)
  }
  hasComponent(componentName) {
    return this.components.find(component => component.name === componentName)
  }
  hasEntity(entityName) {
    return this.entities.find(entity => entity.name === entityName)
  }
  createEntity(name, components) {
    let entity = {name, components}
    components.forEach(component => {
      const componentObject = this.components.find(ecsComponent => component === ecsComponent.name)
      entity = Object.assign(entity, componentObject.state)
    })
    return entity
  }
  
  entityHasComponent(entity, componentName) {
    return entity.components.includes(componentName)
  }
  
  removeComponentFromEntity(entity, componentName) {
    const indexOfComponent = entity.components.indexOf(componentName)
    if (indexOfComponent === -1) {
      throw new Error("Component not found on entity")
    } else {
      entity.components = entity.components.filter(component => component !== componentName)
      const component = ECS.getComponent(componentName)
      const keys = Object.keys(component.state)
      
      keys.forEach(key => {
        delete entity[key]
      })
    }
  }
  
  addComponentToEntity(entity, component) {
    console.log(ECS.entityHasComponent(entity, component.name))
    if (ECS.entityHasComponent(entity, component.name)) {
      return
    }
    entity = Object.assign(entity, component.state ? component.state : {})
    entity.components.push(component.name)
  }
  addEntity(entity) {
    this.entities.push(entity)
  }
  addComponent(component) {
    this.components.push(component)
  }
  addProcessor(processor) {
    this.processors.push(processor)
  }
  getEntitiesFromComponent(componentName) {
    return this.entities.filter(entity => {
      return entity.components.includes(componentName)
    })
  }
  getComponent(componentName) {
    return this.components.find(component => componentName === component.name)
  }
  runProcessors() {
    this.processors.forEach(processor => {
      const entities = this.getEntitiesFromComponent(processor.component)
      const component = this.getComponent(processor.component)
      processor.update(component, entities)
    })
  }
  runCustomLogicOnEntities() {
    this.entities.forEach(entity => {
      if (entity.update) {
        entity.update()
      }
    })
  }
  update() {
    this.runProcessors()
    this.runCustomLogicOnEntities()
  }
}
function gameloop() {
  ECS.update()
  requestAnimationFrame(gameloop)
}
requestAnimationFrame(gameloop)
const ECS = new EntityComponentSystem()
// Components
const positionComponent = {
  name: "position",
  state: {
    x: 0,
    y: 0
  }
}
const sizeComponent = {
  name: "size",
  state: {
    size: 10
  }
}
const renderingComponent = {
  name: "render"
}
const gravityComponent = {
  name: "gravity",
  state: {
    velocity: 0
  }
}
const edgeHandlingComponent = {
  name: "edgeHandler"
}
const redColorComponent = {
  name: "redColor",
  state: {
    color: "red"
  }
}
// register Components
ECS.addComponent(positionComponent)
ECS.addComponent(sizeComponent)
ECS.addComponent(renderingComponent)
ECS.addComponent(gravityComponent)
ECS.addComponent(edgeHandlingComponent)
ECS.addComponent(redColorComponent)
// Processors
const renderingProcessor = {
  name: "RenderProcessor",
  component: "position",
  update(component, entities) {
    ctx.clearRect(0, 0, canvas.height, canvas.width)
    
    entities.forEach(entity => {
      // console.log(entity)
      const {x, y, size} = entity
      
      ctx.beginPath()
      ctx.fillStyle = entity.color ? entity.color : "white"
      ctx.fillRect(x, y, size, size)
      ctx.closePath()
    })
  }
}
const gravityProcessor = {
  name: "GravityProcessor",
  component: "gravity",
  update(component, entities) {
    entities.forEach(entity => {
      entity.velocity += 0.02
      entity.y += entity.velocity
    })
  }
}
const edgeHandlingProcessor = {
  name: "EdgeHandleProcessor",
  component: "edgeHandler",
  update(component, entities) {
    entities.forEach(entity => {
      const {x, y, size} = entity
      
      if (x + size > canvas.width) {
        entity.x = canvas.width - size
      }
      
      if (x < 0) {
        entity.x = 0
      }
      
      if (y < 0) {
        entity.y = 0
      }
      
      if (y + size >= canvas.height) {
        entity.velocity = -entity.velocity
      }
    })
  }
}
// register Processors
ECS.addProcessor(renderingProcessor)
ECS.addProcessor(gravityProcessor)
ECS.addProcessor(edgeHandlingProcessor)
// Entities
const Box = ECS.createEntity("Box", ["position", "size", "render", "gravity", "edgeHandler", "redColor"])
Box.x = Box.y = 100
Box.size = 50
// Add Entities
ECS.addEntity(Box)
// ECS.removeComponentFromEntity(Box, "gravity")
Output

This bin was created anonymously and its free preview time has expired (learn why). — Get a free unrestricted account

Dismiss x
public
Bin info
anonymouspro
0viewers