# Getting started Tecs combines a typed entity component system with a game engine for Teal and LuaJIT. Game state, rendering, audio, physics, and tools share the same world. ## Install the CLI The [Tecs CLI](/cli/) carries the engine, project toolchain, template, and offline reference: ```bash tecs new my-game cd my-game tecs run ``` The generated `tecs.lua` marks the project root and names its entry file. Project commands work from any directory below it. ## Build this repository Contributors build the engine through Cargo: ```bash git clone https://github.com/tecs-dev/tecs.git cd tecs cargo xtask deps cargo xtask build cargo xtask test cargo xtask example ui-demo cargo xtask example gltf3d ``` `cargo xtask deps` installs system development dependencies. The repository pins Teal, the formatter, and tealdoc revisions for every checkout. `--preset` selects a target. Development presets use system libraries. Package presets build pinned dependencies from source: ```bash cargo xtask presets cargo xtask test # run Rust, ABI, and Lua/Teal tests cargo xtask package --preset macos-arm64 cargo xtask check-package out/package ``` ## Entry file The host owns the loop. The entry file returns an application: ```teal return tecs.newApplication({ window = { title = "Hello", width = 1280, height = 960, }, plugin = function(world: tecs.World, app: tecs.Application) -- Register the game here. end, }) ``` The host loads `tecs` before the entry file, so game code uses it as a global. A headless script or spec loads the same table explicitly: ```teal local tecs = require("tecs") ``` See [`tecs.Application`](/modules/Application) for lifecycle and configuration. ## First plugin The entry plugin registers systems, observers, resources, and entities: ```teal local Transform2D = tecs.Transform2D return tecs.newApplication({ plugin = function(world: tecs.World, app: tecs.Application) local movers = world:newQuery({ include = {Transform2D}, }) world:addSystem({ name = "game.Spin", phase = tecs.ecs.phases.Update, run = function(dt: number) for archetype, length in movers:iter() do local transforms = archetype:getMut( Transform2D ) for row = 1, length do transforms[row].rotation = transforms[row].rotation + dt end end end, }) world:spawn(Transform2D(100, 100)) end, }) ``` Keep three rules visible when writing systems: - Create persistent queries during plugin setup. - Read columns with `get` and mark written columns with `getMut`. - Run `query:iter()` to exhaustion. Use `query:newCursor()` and close it when a loop may stop early. The [mutation model](/modules/ecs/mutation-model) covers deferred changes and dirty tracking. ## Optional transparent meshes Opaque mesh rendering keeps its original three-pass cull chain. Enable the separate transparent resources only when a game needs glTF `BLEND` materials or registers an `ALPHA_BLEND` material itself: ```teal return tecs.newApplication({ sprites = false, meshes = { transparency = true, }, plugin = function(world: tecs.World, app: tecs.Application) tecs.assets.loadGLTF( tecs.io.files.assetPath("models/glass.gltf") ):onSettle(function(loaded: tecs.Future) if loaded.status ~= "ready" then error(loaded.error, 0) end for _, primitive in ipairs( app.renderer.meshes:registerModel(loaded.value) ) do world:spawn( primitive.transform, primitive.mesh, primitive.bounds, primitive.material, tecs.gfx.Tint(), tecs.gfx.Renderable3D() ) end end) end, }) ``` The mesh domain frustum-culls and depth-sorts complete indexed commands on the GPU. It draws transparent meshes before the sprite forward lane, so sprites retain deterministic overlay ordering in a renderer that enables both domains. ## Game modules Split a game into plugins and install them from the entry plugin: ```teal local enemies = require("game.enemies") local movement = require("game.movement") return tecs.newApplication({ plugin = function(world: tecs.World, app: tecs.Application) world:addPlugin(movement.plugin) world:addPlugin(enemies.plugin) end, }) ``` The host adds the project content root to `package.path`, so `require("game.enemies")` loads `game/enemies.lua`. ## Next pages - [tecs.ecs](/modules/ecs/) introduces worlds, components, queries, and systems. - [Modules](/modules/) lists every public engine module. - [Tecs CLI](/cli/) covers project commands and the offline reference.