npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

lilis-engine

v1.0.0

Published

This game engine is very modular, simple, and highly adaptable. It's adaptability comes from the intentional support for developing plugins which can suit any use case. This game engine is also designed from the ground up to work entirely using **function

Downloads

104

Readme

Lili's Game Engine

This game engine is very modular, simple, and highly adaptable. It's adaptability comes from the intentional support for developing plugins which can suit any use case. This game engine is also designed from the ground up to work entirely using functional programming instead of object oriented programming, which I believe is a much better design pattern.

This game engine takes inspiration from web frameworks like Astro.build which emphasize clean code and interoperability as a fundamental design principle, rather than an afterthought. Many coding projects incur massive technical debt under a "ship now, fix later" mindset, which inevitably leads to large amounts wasted time which could have been prevented with more forethought. I spent multiple years designing this game engine, even rebuilding it from scratch so that it will stand the tests of time and save developers time and headaches. I did this by inventing cleaner and more effective design patterns that serve as the foundation of your game, primarily two things serve as the bedrock of the game engine:

  1. Functional Programming
  2. Signals

Signals are a concept borrowed a web UI library called SolidJS, but I built my own implementation of them called Jabr which has been disentangled from the specifics of web UI libraries. Basically we can take one of the most powerful tools from cutting edge web development and apply it to game development. In practical terms it's like a variable that we can automatically listen for changes in it's value. They are extremely flexible, and I believe they can be used to sidestep the messiness that arises when using classes in Object Oriented Programming! Instead of classes we can use callbacks, and JavaScript's async feature makes coordinating events and tasks across time simple.

More On Signals

Here is some example of how Jabr can be used in game development:

import {Signal} from 'jabr'
const [getPlayerPos, setPlayerPos, addPlayerPosListener, removePlayerPosListener] = new Signal({x: 0, y: 10})

const playerPositionListener = (newValue, oldValue) => {
	console.log('New Player Position: ' + newValue)
	console.log('Old Player Position: ' + oldValue)
}

addPlayerPosListener(playerPositionListener)

setPlayerPos({x: 8, y: -99}) // Now our listener is called, logging our old and new player positions

removePlayerPosListener(playerPositionListener)

setPlayerPos({x: 99, y: -190}) // Nothing is logged because we removed our listener

By passing this player signal to our physics engine we no longer need to manually tell the physics engine when our player position changes, or create custom listeners to handle the physics engine updating the player position. There is now a single source of truth for this player position variable that allows us to gracefully handle updates without needing to rely on a tangled web of classes. My game engine expands on this concept, giving you an effective base for your game engine that is written in as few lines of code as possible so you can study it inside and out and customize it to your heart's content.

Diving into an example usage of the game engine

Enough technical breakdown of why I love this game engine, let's dive into an example of how it looks in practice. Below is some example code, notice how each component of the game engine is manually initialized. While that does increase the number of lines of code by a small amount, it leaves room for you to swap these plugins out with your own choice of plugins. Yes, even the default core behaviors of the game engine are themselves plugins with easily inspectable source code. Without further adieu:

import createP5Renderer from "./createP5Renderer";
import createGameCore from "./createGameCore";
import createGameLoop from "./createGameLoop";
import createEntity from "./createEntity";
import createEntityList from "./createEntityList";
import createRenderSettings from "./createRenderSettings";
import { details } from "sandhands";

export default async function runGame(container) {
  const entity = createEntity();
  const entities = createEntityList([entity]);
  window.entities = entities;
  const renderSettings = createRenderSettings({
    container,
    setup: (p) => {
      console.log(p);
      p.createCanvas(1000, 1000);
      p.background(200);
    },
  });
  const gameCore = createGameCore({
    plugins: [createGameLoop(), createP5Renderer(entities, renderSettings)],
  });
  gameCore.events.on("tick", () => {
    entity.x = (entity.x + 1) % 100;
  });
  await gameCore.mount();
  return gameCore.unmount;
}

Here we setup our plugins, tell the p5.js renderer how to initialize the canvas, and create an on-screen entity that automatically moves left-to-right across the screen in about 30 lines of code. While a full functional game would take more than this, this example highlights all of the most basic functionality that you need to make a game with the engine! While that is a neat feat, I am confident that this simplicity scales to even flushed out games because I battle tested it in my first published game Drawlf!