Tjakka5

Untitled

Aug 25th, 2018
450
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 3.82 KB | None | 0 0
  1. local Ffi = require("ffi")
  2. local Lds = require("lds")
  3. local Bit = require("bit")
  4.  
  5. local EntityCount = 50000
  6.  
  7. local Open = {}
  8. local References    = {}
  9. local ReferencesIDs = {}
  10.  
  11. local function newReference(v)
  12.    local fromOpen = #Open > 0
  13.    local id = (fromOpen and Open[#Open]) or #References + 1
  14.  
  15.    References[id] = v
  16.    ReferencesIDs[v] = id
  17.  
  18.    if fromOpen then
  19.       fromOpen[id] = nil
  20.    end
  21.  
  22.    return id
  23. end
  24.  
  25. local nextMask = 1
  26. local function newComponent(struct)
  27.    local type     = Ffi.metatype(Ffi.typeof("struct {"..struct.."}"), {
  28.       __index = function(self, key)
  29.          return References[self["_"..key]]
  30.       end,
  31.  
  32.       __newindex = function(self, key, value)
  33.          local key = "_"..key
  34.  
  35.          local oldValue = self[key]
  36.  
  37.          if oldValue then
  38.             -- oldValue is an ID for in the reference table
  39.             -- We need to manually track how many references there are.
  40.             -- If nothing is referencing the object, it should be removed.
  41.          end
  42.  
  43.          self[key] = ReferencesIDs[value] or newReference(value)
  44.       end
  45.    })
  46.    local entities = Lds.Array(type, EntityCount)
  47.    local mask     = nextMask
  48.  
  49.    nextMask = nextMask * 2
  50.  
  51.    return {
  52.       type     = type,
  53.       entities = entities,
  54.       mask     = mask,
  55.    }
  56. end
  57.  
  58. local systems = {}
  59. local function newSystem(filter)
  60.    local mask     = 0
  61.    local entities = Ffi.new("int[?]", EntityCount)
  62.    local items    = 0
  63.  
  64.    for _, component in ipairs(filter) do
  65.       mask = mask + component.mask
  66.    end
  67.  
  68.    local system = {
  69.       mask     = mask,
  70.       entities = entities,
  71.       items    = items,
  72.    }
  73.  
  74.    systems[#systems + 1] = system
  75.  
  76.    return system
  77. end
  78.  
  79. local nextID = 0
  80. local function newEntity()
  81.    local id   = nextID
  82.    local mask = 0
  83.  
  84.    nextID = nextID + 1
  85.  
  86.    return {
  87.       id   = id,
  88.       mask = mask,
  89.    }
  90. end
  91.  
  92. local function giveComponent(e, component, ...)
  93.    local comp = component.type(...)
  94.  
  95.    component.entities:set(e.id, comp)
  96.    e.mask = e.mask + component.mask
  97.  
  98.    return comp
  99. end
  100.  
  101. local function filter(e)
  102.    for _, system in ipairs(systems) do
  103.       if bit.band(e.mask, system.mask) == system.mask then
  104.          system.entities[system.items] = e.id
  105.          system.items = system.items + 1
  106.       end
  107.    end
  108. end
  109.  
  110. local Position = newComponent([[
  111.    float x, y;
  112. ]])
  113.  
  114. local Velocity = newComponent([[
  115.    float x, y;
  116. ]])
  117.  
  118. local Sprite = newComponent([[
  119.    int _texture;
  120. ]])
  121.  
  122. local Physics        = newSystem({Position, Velocity})
  123. local SpriteRenderer = newSystem({Position, Sprite})
  124.  
  125. local texture = love.graphics.newImage("stone.png")
  126. local texture_id = newReference(texture)
  127.  
  128. for i = 1, EntityCount do
  129.    local myEntity = newEntity()
  130.    giveComponent(myEntity, Position, 0, 0)
  131.    giveComponent(myEntity, Velocity, love.math.random(10, 30), love.math.random(10, 30))
  132.    giveComponent(myEntity, Sprite, texture_id)
  133.  
  134.    filter(myEntity)
  135. end
  136.  
  137. local maxX, maxY = love.graphics.getWidth(), love.graphics.getHeight()
  138. function love.update(dt)
  139.    for i = 1, Physics.items do
  140.       local id = Physics.entities[i - 1]
  141.  
  142.       local position = Position.entities:get(id)
  143.       local velocity = Velocity.entities:get(id)
  144.  
  145.       position.x = position.x + velocity.x * dt
  146.       position.y = position.y + velocity.y * dt
  147.  
  148.       if position.x > maxX or position.y > maxY then
  149.          position.x = 0
  150.          position.y = 0
  151.       end
  152.    end
  153.  
  154.    love.window.setTitle(love.timer.getFPS())
  155. end
  156.  
  157. function love.draw()
  158.    for i = 1, SpriteRenderer.items do
  159.       local id = SpriteRenderer.entities[i - 1]
  160.       local position = Position.entities:get(id)
  161.       local sprite   = Sprite.entities:get(id)
  162.  
  163.       local texture = sprite.texture
  164.       --love.graphics.draw(sprite.texture, position.x, position.y, nil, 0.25, 0.25)
  165.    end
  166. end
Advertisement
Add Comment
Please, Sign In to add comment