flodihn

flodihn

Hello, I chose to use Elixir as “scripting” language for my game, I am very new to Elixir but I know Erlang well.
My goal is to somewhat replicate LPC, which is an object oriented langage in C for LP Muds which used a lot back in the days.

So far I managed to come by borrowing examples from an OOP lib I found here: oop/lib/oop.ex at master · wojtekmach/oop · GitHub

What I want to do is to define game objects, and let them “inherit” from a parent object, like this:

Ao.ShortSword -> Ao.Weapon -> Ao.Object

This is done by defining an object macro that lets me inherit from one other object with the :: expression, for example Ao.Weapon :: Ao.Object
If the object macro detects the precense of an inherited object, it will create delegates for all methods in the parent and delegate from the object to the parent.

So far everything works like a charm, but now I need to add “properties” to the objects. A property is a key,value that describes the object some how, for example:

set_property(:colors, [{:red, 80, :yellow, 20}])
set_property(:materials: [{:bronze, 100}])
set_property(:mesh, <<"BronzeShortSword.fbx">>)

The issue I am trying to solve now that not all properties are equal, they are divided into shallow and deep properties. Shallow properties are things that I expect
to be queried more than 99.99% of the times, in most cases this would be properties like:

:position
:rotation
:mesh

These would be saved in a mnesia table for quick access.

And then all other properties that will only be queried or written in rare cases are saved in a long term (slower) database, such as Riak.
To define this I thought I could use Elixirs built-in attribute system, for example:

object Ao.Weapon :: Ao.Object do
    @shallow :position
    @shallow :rotation
    @shallow :mesh

The problem I face is that the Ao.Object.set_property needs to know the objects (Ao.Weapon) shallow attributes so it can store the value in the mnesia DB
instead of Riak, but can not access it because they are stored in Ao.Weapon.
Right now I am considering defining the set_property function in a macro when creating the module using the object macro, but to be honest, I have literally no idea what is a good approach for this.

I hope that someone can guide me towards a good solution.

Here is the code I have so far, please note at Code.eval_quoted(method, [], __ENV__) I add the delegate, maybe a good solution would be to pass the module Ao.Weapon to the Ao.Object.set_property there:

defmodule Ao do
  defmacro object(obj_expr, block, _opts \\ []) do
    {object, parent} = case obj_expr do
      {:"::", _, [obj, parent]} ->
        {obj, parent}
      obj ->
        {obj, nil}
    end

    AoLibObj.Builder.build(object, parent, block)
  end
end

defmodule AoLibObj.Builder do
  def build(object, parent, block) do
    quote do

      defmodule unquote(object) do
        parent_obj = unquote(parent)

        Module.register_attribute(__MODULE__, :parent, accumulate: false)
        Module.put_attribute(__MODULE__, :parent, parent_obj)

        Module.register_attribute(__MODULE__, :shallow, accumulate: true)

        unquote(block)

        def methods do
          built_ins = [
            object: 0, methods: 0, clone: 1
          ]

          __MODULE__.__info__(:functions) -- built_ins
        end

        if parent_obj != nil do
          for {fun, arity} <- parent_obj.methods() do
            method = AoLibObj.Builder.inherit_method(fun, arity, parent_obj)
            Code.eval_quoted(method, [], __ENV__)
            IO.inspect(fun)

          end
        end

        def clone(uid \\ nil) do
          uid = if uid == nil do AoLibObj.Builder.make_uid() else uid end
          %{
            :uid => uid,
            :object => unquote(object),
          }
        end
      end
    end
  end

  def inherit_method(method, arity, parent_obj) do
    args = (0..arity) |> Enum.drop(1) |> Enum.map(fn i -> {:"arg#{i}", [], Ao} end)
    IO.inspect(args)
    {:defdelegate, [context: Ao, import: Kernel],
      [{method, [], args}, [to: parent_obj]]}
  end

  def make_uid() do
    <<a::32, b::16, c::16, d::16, e::48>> = :crypto.strong_rand_bytes(16)

    str =
      :io_lib.format(
        "~8.16.0b-~4.16.0b-4~3.16.0b-~4.16.0b-~12.16.0b",
        [a, b, Bitwise.band(4095, c), Bitwise.band(16383, d), Bitwise.bor(32768, e)]
      )

    :erlang.list_to_binary(str)
  end
end




import Ao

object Ao.Object do

  def init() do
    IO.puts("Instanced Ao.Object!")
  end

  def set_property(_key, _value, child \\ nil ) do
    IO.puts("BASE!!! Ao.Object")
  end
end



import Ao

object Ao.Weapon :: Ao.Object do
  @shallow :position
  @shallow :rotation
  @shallow :mesh
end

Showing Posts 1 to 4

stevensonmt

stevensonmt

I hope someone with more experience chimes in, but I think it is important to recognize that trying to shoe-horn object oriented paradigms like inheritance is destined to fall short in Elixir. Inheritance just is not part of the language by design.

I would recommend you define behaviours for your “object classes” and then have each specific module implement the behaviours it requires. So a sword can implement weapon behaviour, and a shovel can implement weapon behaviour and tool behaviour and so on.

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

Hey @flodihn, sounds like an interesting space! As @stevensonmt says though, this:

is not a strategy that I think will lead you to success. You should re-envision your requirements to match a functional language, or pick a scripting language with objects and inheritance built in. Attempting to shoehorn it into Elixir is going to be both very difficult and also very lonely, because there really aren’t other people in the ecosystem attempting to do it.

EDIT: I suppose a third, sort of “out there” answer would be to implement an LPC runtime in Elixir such that you could just straight up use LPC as your game scripting language. This is by no means the most efficient use of time, but could be a lot of fun!

kokolegorille

kokolegorille

You could use luerl, lua on the BEAM.

There is a spaceship game demo by @rvirding and videos on YT about luerl.

andyleclair

andyleclair

You should actually watch the youtube video linked in the OOP repo.

It is not serious, and you should not take it as a good example.

If you want an Entity Component System, you may want to try GitHub - ecsx-framework/ECSx: An Entity-Component-System framework for Elixir · GitHub

— All posts loaded —

Where Next? Top

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
water
I’m aware of 2 such projects, are there others? git: GitHub - team-alembic/realworld: A fullstack Phoenix LiveView application with back...
New
itzmidinesh
Hi all, I’m working on a Phoenix project where I need to make external HTTP requests and I’m trying to choose between Req and HTTPoison....
New
pragdave
How do I tell Hologram not to escape HTML when substituting into templates? {Textile.render(@product.long_description)} escapes the HTM...
New
leoschweizer
Hi, we run different LLM models across a cluster, with each node loading a configurable subset. Model-specific queues let nodes consume ...
New
Stef-Verniers
Hello I’ve been coding in Elixir for almost two years now because of my current job where we implemented Elixir in our application. But ...
New
csmr
Hi all, I’m new here and would like to hear peoples views on my Elixir/Phoenix based game-engine! :smiley: Mutonex gamedesign was finish...
New

Other Trending Topics Top

dominicletz
Hey there, I haven’t seen a list of useful Elixir specific skills for the popular AI tools yet so I’m starting one here with my first. ...
New
raa-ziq
Hi everyone :waving_hand: I wanted to share something I’ve been building — NowBlind, a random chat app designed to help people discover ...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
kip
Localize is the next generation localisation library for Elixir. Think of it as ex_cldr version 3.0. The first version will be released ...
New
OndrejValenta
(I just needed to vent somewhere and LinkedIn is full of hope, or hype, I’m not sure which exactly) AI dream has many faces, but general...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews