Coder Social home page Coder Social logo

domeengine / dome Goto Github PK

View Code? Open in Web Editor NEW
465.0 11.0 40.0 41.07 MB

A lightweight game development environment where games can be written in Wren

Home Page: https://www.domeengine.com

License: MIT License

Makefile 0.27% C 97.24% Shell 0.15% NASL 0.06% JavaScript 2.05% HTML 0.23%
games gamedev wren engine sdl2 c hacktoberfest

dome's Introduction

DOME - Design-Oriented Minimalist Engine

A comfortable framework for game development which melds SDL2 and the Wren scripting language, written in C.

Image of DOME logo

For more information on how to use DOME and get started, read the docs here.

How to Use

Download

You can download production-ready binaries from our Releases page. This is the recommended method for distribution and easy development.

Install via Brew

Alternatively, if you have Homebrew installed (Mac OS X, Linux and WSL), you can install DOME using the following commands:

> brew tap domeengine/tap
> brew install dome

Build

Finally, if you want to build DOME yourself, to make modifications or other reasons, follow these instruction instead.

Ensure you have the shared SDL2 libraries installed on your system first, then to build, run:

> make

This will create an executable named ./dome (on Mac OS X and Linux), and ./dome-x32.exe or ./dome-x64.exe.

Run

Run ./dome [gamefile.wren] to run your game. If your initial file is called main.wren, just running ./dome will execute it. Replace dome with your built binary name as necessary.

Basics

Your game's entry point must contain a Game variable which contains at least init(), update() and draw(_) methods.

import "input" for Keyboard
import "graphics" for Canvas, Color

class Main {
  construct new() {}

  init() {
    _x = 10
    _y = 10
    _w = 5
    _h = 5
  }

  update() {
    if (Keyboard.isKeyDown("left")) {
      _x = _x - 1
    }
    if (Keyboard.isKeyDown("right")) {
      _x = _x+ 1
    }
    if (Keyboard.isKeyDown("up")) {
      _y = _y - 1
    }
    if (Keyboard.isKeyDown("down")) {
      _y = _y + 1
    }
  }

  draw(alpha) {
    Canvas.cls()
    var color = Color.rgb(171, 82, 54)
    Canvas.rectfill(_x, _y, _w, _h, color)
  }
}

var Game = Main.new()

Modules

DOME provides the following features, and more:

  • Graphics
    • Canvas
      • Rect
      • Point
      • Circle
      • Ellipses
      • Lines
      • Triangles
    • Color
    • ImageData (aka Bitmap)
      • Draw sprites loaded from files (png)
    • SpriteSheet support
  • Input
    • Keyboard
    • Mouse
    • Gamepads
  • Filesystem
    • File reading and writing
  • Audio (stereo and mono OGG, MP3, FLAC and WAV files)
  • Collections (abstact types)
    • Set
    • Queue
    • Stack
    • Priority Queue
  • Native Plugins (allowing access to all kinds of functionality!)

TODO

You can follow my progress on implementing DOME on my twitter.

  • Graphics
    • Potential 3D rendering mode?
  • IO
    • Asynchronous Operations
  • Network Access
    • UDP
    • HTTP client (maybe)
  • Security sandboxing (maybe)

Dependencies

DOME currently depends on a few libraries to achieve it's functions.

  • Wren (included in the project repo already)
  • SDL2 (version 2.26.3. If you install this from source, you'll want to build shared/dynamic libraries.)
  • utf8.h
  • stb_image
  • stb_image_write
  • stb_truetype
  • stb_vorbis
  • microtar
  • optparse
  • jo_gif
  • tinydir
  • ABC_fifo (A SPMC threadpool/task dispatching FIFO I wrote for this project)
  • mkdirp
  • whereami
  • dr_mp3
  • dr_flac

Apart from SDL2, all other dependancies are baked in. DOME aspires to be both minimalist and cross platform, so it depends on as few external components as possible.

Acknowledgements

Example Game Resources

  • Example game and graphics are derived from this fantastic PICO-8 tutorial.
  • Aerith's Piano Theme (res/AerisPiano.ogg) by Tanner Helland is available under a CC BY-SA 3.0 license: Link
  • Game Over Theme (res/music.wav) by Doppelganger is available under a CC BY-SA 3.0 license: Link
  • Font "Memory" is provided by Eeve Somepx, and is available on their patreon here under a common sense license.

dome's People

Contributors

8-bit-dev avatar avivbeeri avatar catsanddo avatar chayimfriedman2 avatar clsource avatar confusedsky avatar frarees avatar kasparsu avatar purefox48 avatar scholar-mage avatar siddhantrao23 avatar theking0x9 avatar trelemar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dome's Issues

Better command-line argument handling

There's a TODO in the code related to using getopt to parse command line arguments.

There's also currently no way to get the program usage information if DOME finds an egg or main.wren file since it will be automatically loaded. It'd be nice to have a -h and/or --help flag.

[idea] Support command line params in Wren

Dome could provide some API to access command line params.
So games can change their behaviours depending on these params.

Some quick draft

import "dome" for Args
class Game {
    static init() {
           Args.dome // A Map that stores the argv with DOME specific params (like --debug)
          Args.app // A Map that stores the argv with all the other Not standard DOME params
         Args.all // Args.dome + Args.app params
    }
}

Add iget() or ImageData.pget() function

Hi! I really like this project so far. :)

I think it would be useful to get colors from images, not just from the canvas. Since you seem to be inspired by PICO-8, think of it as the sget() function from the PICO-8 API. This would be useful to for example store a collision map of a game with white for solid objects, black/transparent for background elements.

Drawing to the canvas using ImageData.drawArea then using Canvas.pget works fine enough, but I thought this would make a great little addition to the DOME API. :)

IMAGE_allocate will attempt to load a nonexistent file, causing a crash

Dome will attempt to load invalid resource paths, which causes a segfault. For example, rename ship1.png to something else, and you'll get the following crash:

Loading module audio
Loading module input
Loading module graphics
Loading module point
Loading module random
Loading module io

Thread 1 "dome" received signal SIGSEGV, Segmentation fault.
0x000055555556ed75 in stbi__get8 (s=0x7fffffffbb30) at src/include/stb_image.h:1409
1409	      return *s->img_buffer++;
(gdb) where
#0  0x000055555556ed75 in stbi__get8 (s=0x7fffffffbb30) at src/include/stb_image.h:1409
#1  0x0000555555575e26 in stbi__get_marker (j=0x5555576b5500) at src/include/stb_image.h:2660
#2  0x000055555557866c in stbi__decode_jpeg_header (z=0x5555576b5500, scan=1)
    at src/include/stb_image.h:3098
#3  0x000055555557bc04 in stbi__jpeg_test (s=0x7fffffffbb30) at src/include/stb_image.h:3750
#4  0x000055555556dc4f in stbi__load_main (s=0x7fffffffbb30, x=0x5555576b54d8, y=0x5555576b54dc, 
    comp=0x5555576b54e0, req_comp=4, ri=0x7fffffffbadc, bpc=8) at src/include/stb_image.h:980
#5  0x000055555556e0c9 in stbi__load_and_postprocess_8bit (s=0x7fffffffbb30, x=0x5555576b54d8, 
    y=0x5555576b54dc, comp=0x5555576b54e0, req_comp=4) at src/include/stb_image.h:1088
#6  0x000055555556e7ec in stbi_load_from_memory (buffer=0x0, len=1431883287, x=0x5555576b54d8, 
    y=0x5555576b54dc, comp=0x5555576b54e0, req_comp=4) at src/include/stb_image.h:1226
#7  0x0000555555567f5e in IMAGE_allocate (vm=0x5555575c2c20) at src/engine/image.c:19
#8  0x000055555558b3ff in runInterpreter ()
#9  0x0000555555569deb in main (argc=1, args=0x7fffffffde58) at src/main.c:172

Support newline for fonts when printing

Currently when a newline is in Canvas.print(), it's shown as a square like a wrong symbol.

The fix itself seems quite simple, I just ran into make issues, with the Wren library, platform and SDL2, but I think I have the solution to fixing newlines themselves. I'm also not too experienced with C.

dome/src/modules/font.c

Lines 94 to 115 in ffc47ca

for (int charIndex = 0; charIndex < len; charIndex++) {
int ax;
int lsb;
int oY, oX;
stbtt_GetCodepointHMetrics(&info, codepoint, &ax, &lsb);
bitmap = stbtt_GetCodepointBitmap(&info, 0, scale, codepoint, &w, &h, &oX, &oY);
posX += oX;
posY = baseY + oY;
uint32_t outColor;
float baseAlpha = ((color & 0xFF000000) >> 24) / (float)0xFF;
for (int j = 0; j < h; j++) {
for (int i = 0; i < w; i++) {
if (raster->antialias) {
uint8_t alpha = baseAlpha * bitmap[j * w + i];
outColor = (alpha << 24) | (color & 0x00FFFFFF);
} else {
outColor = bitmap[j * w + i] > 0 ? color : 0;
}
ENGINE_pset(engine, posX + i, posY + j, outColor);
}
}

So currently it goes through each character, here we could check if the character is \n, which instead of running Engine.pset() we could increment a newline counter, that we use for multiplying the height of the font with and add that to the posY.

So instead of:
ENGINE_pset(engine, posX + i, posY + j, outColor);
We do:
ENGINE_pset(engine, posX + i, posY + (fontHeight * newlines) + j, outColor);

The x position should probably be reset on a newline.

Panning values only work at -1.0 and 1.0

Hi there,

I am working on an audio game (no graphics) and was planning to use DOME to build it. I spent some time messing with the audio module and was working on simulating surround sound.

I noticed that different values of panning weren't working at values in between -1.0 and 1.0, only exactly -1.0 and 1.0 will pan left and right, respectively.

I have attached a ready-to-run .zip with a working example of the issue.

  • Use left and right arrows to adjust panning value.
  • Use up and down arrows to flip front and back sound (not necessary, just something I'd already been working on, so it was already in there).

PanningBugExample.zip

[Plugin] Base64 to/from ImageData

I'm writing this to have an issue to refer to when the plugins system is available.

Some tools like Ogmo https://github.com/Ogmo-Editor-3/ogmo-3-lib/blob/master/res/test.ogmo#L243
embed images as a https://www.base64encode.org/ string.

Base64 could be used to encoded other mediatypes, but mainly is used for images.

A sample implementation of Base64 could be from

https://github.com/megamarc/Tilengine/blob/master/src/Base64.c

Proposed api

ImageData.loadFromBase64(content: String): ImageData
image.toBase64

Arbitrary Sprite Transformations

DOME supports rotation (in 90 degree increments) and integer scaling, but I'd like to allow for arbitrary transformations (including skews and full 360 degree rotations).

This will matter more to people operating at higher resolutions. It's also essential that it be as performant as possible.

Improve CONTRIBUTING.md with code style and design guidelines

The way API's are designed and documented in DOME are intentionally strict, to maintain its value of minimalism, and this should be made clear in the CONTRIBUTING.md file, along with project issue templates.

In addition, code style should be described in greater detail to allow contributions to match.

Canvas.line seems to reach incorrect endpoint

Hi, I'm testing out a few small DOME features to familiarise myself ahead of DOME jam :)

I'm trying out some alternate screen sizes (in this case 400x240px) and noticed that drawing a line from one corner of the screen to another doesn't seem to behave as expected.

With this example code I get the following result:

import "dome" for Window
import "graphics" for Canvas, Color

class Game {
    static init() {
      Window.resize(400, 240)
      Canvas.resize(400, 240)
    }
    static update() {}
    static draw(dt) {
      Canvas.rect(0, 0, 400, 240, Color.white)
      Canvas.line(0, 0, 400, 240, Color.blue)
      Canvas.print("%(Canvas.width)", 1, 1, Color.red)
      Canvas.print("%(Canvas.height)", 1, 10, Color.red)
    }
}

image

Notice how the rect() function with width/height matching the screen correctly draws a border from one corner of the screen to another, however the line drawn with line() does not touch the corner of the screen as I'm expecting.

I'm not sure if this is related to the specific screen size I've chosen or just the line function in general, but in any case this doesn't match how I'd expect it to behave.

Thanks!

[feature] Add FPS counter

Currently, the engine supports showing FPS by pressing F3.
But this code is hardcoded in C.

https://github.com/avivbeeri/dome/blob/master/src/engine.c#L874

internal void
ENGINE_drawDebug(ENGINE* engine) {
  char buffer[20];
  ENGINE_DEBUG* debug = &engine->debug;
  // Choose alpha depending on how fast or slow you want old averages to decay.
  // 0.9 is usually a good choice.
  double framesThisSecond = 1000.0 / (debug->elapsed+1);
  double alpha = debug->alpha;
  debug->avgFps = alpha * debug->avgFps + (1.0 - alpha) * framesThisSecond;
  snprintf(buffer, sizeof(buffer), "%.01f fps", debug->avgFps);   // here 2 means binary
  int32_t width = engine->width;
  int32_t height = engine->height;
  int64_t startX = width - 4*8-2;
  int64_t startY = height - 8-2;

  ENGINE_rectfill(engine, startX, startY, 4*8+2, 10, 0x7F000000);
  ENGINE_print(engine, buffer, startX+1,startY+1, 0xFFFFFFFF);

  startX = width - 9*8 - 2;
  if (engine->vsyncEnabled) {
    ENGINE_print(engine, "VSync On", startX, startY - 8, 0xFFFFFFFF);
  } else {
    ENGINE_print(engine, "VSync Off", startX, startY - 8, 0xFFFFFFFF);
  }

  if (engine->lockstep) {
    ENGINE_print(engine, "Lockstep", startX, startY - 16, 0xFFFFFFFF);
  } else {
    ENGINE_print(engine, "Catchup", startX, startY - 16, 0xFFFFFFFF);
  }
}

It would be handy to obtain the current FPS number in Wren.

Example:

Process.fps

Add final Wren API methods to plugin API.

At this point, we should probably go through and add all the other relevant Wren VM functions which depend on the slot array:

  • WrenCall
  • WrenInterpret
  • wrenHasModule
  • wrenHasVariable
  • wrenSetSlotNewList
  • wrenSetSlotNewMap

And possibly others I missed?

Originally posted by @avivbeeri in #173 (comment)

Best practice for VCS

There should be an established best practice for working with VCS.

Initially I just checked the executable in, but this doesn't work if you're working on multiple platforms. My second approach was to use a symlink, but as it turns out the loading is done relative to the binary path, not relative to the symlink.

My other main thoughts are:

  • A start script that detects the platform and launches the correct binary (only useful for mac/linux)
  • Adding the dome repo as a submodule (still has the symlink problem, and you now have to make every time you want to build on a new computer)

Use of possibly uninitialized variables

This is probably a pretty minor concern, but when optimizations are enabled (-O2 -flto), gcc complains about use of a couple of possibly uninitialized variables:

src/engine/audio.c: In function โ€˜AUDIO_allocateโ€™:
src/engine/audio.c:139:25: warning: โ€˜channelsInFileโ€™ may be used uninitialized in this function [-Wmaybe-uninitialized]
     data->spec.channels = channelsInFile;
                         ^
src/engine/audio.c:133:9: note: โ€˜channelsInFileโ€™ was declared here
     int channelsInFile, freq;
         ^
src/engine/audio.c:140:21: warning: โ€˜freqโ€™ may be used uninitialized in this function [-Wmaybe-uninitialized]
     data->spec.freq = freq;
                     ^
src/engine/audio.c:133:25: note: โ€˜freqโ€™ was declared here
     int channelsInFile, freq;
                         ^

Unable to run main.wren with OSX binary

Not sure if I'm just doing this incorrectly or what.

When I download the latest OSX binary release .zip, unzip it and put the dome executable in the same root level directory as the main.wren file of my game, I get the following terminal message. I'm assuming that I get this because it can't find my main.wren file for some reason? Help would be greatly appreciated.

Last login: Sun May  3 19:09:10 on ttys001
/Users/skelteon/Desktop/COB_OSX/dome-1.1.1-macosx-x64/dome ; exit;

The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.
Dres-MacBook-Pro:~ skelteon$ /Users/skelteon/Desktop/COB_OSX/dome-1.1.1-macosx-x64/dome ; exit;
Error: Could not find a default entry path.


Usage: 
  dome [-d | --debug] [-r<gif> | --record=<gif>] [-b<buf> | --buffer=<buf>] [entry path]
  dome -h | --help
  dome -v | --version

Options: 
  -b --buffer=<buf>   Set the audio buffer size (default: 11)
  -d --debug          Enables debug mode
  -h --help           Show this screen.
  -v --version        Show version.
  -r --record=<gif>   Record video to <gif>.
logout
Saving session...
...copying shared history...
...saving history...truncating history files...
...completed.

[Process completed]

Ogg files inside eggs cause an assertion failure

Eggs can contain ogg files, but it looks like the audio engine doesn't load them appropriately, and instead causes an assertion failure. This is reproducible on both Windows and Linux.

Loading bundle /home/brian/projects/wren/gamepad/game.egg
Reading tar: ./main.wren
Reading from tar: ./main.wren
Loading module audio
Loading module input
Loading module graphics
Loading module point
Loading module random
Loading module ./test
Reading tar: ./test.wren
Reading from tar: ./test.wren
New Module
Loading module io
Reading tar: ./res/ship1.png
Reading from tar: ./res/ship1.png
Image loaded: res/ship1.png
Reading tar: ./res/ship2.png
Reading from tar: ./res/ship2.png
Image loaded: res/ship2.png
Reading tar: ./res/enemy.png
Reading from tar: ./res/enemy.png
Image loaded: res/enemy.png
Reading tar: ./res/heart-full.png
Reading from tar: ./res/heart-full.png
Image loaded: res/heart-full.png
Reading tar: ./res/heart-empty.png
Reading from tar: ./res/heart-empty.png
Image loaded: res/heart-empty.png
Reading tar: ./res/Laser_Shoot.wav
Reading from tar: ./res/Laser_Shoot.wav
Frequency: 44100 Hz
Samples: 4096
Channels: 1
Format: Signed 16 bit (LSB)
Audio loaded: res/Laser_Shoot.wav
Reading tar: ./res/Explosion.wav
Reading from tar: ./res/Explosion.wav
Frequency: 44100 Hz
Samples: 4096
Channels: 1
Format: Signed 16 bit (LSB)
Audio loaded: res/Explosion.wav
Reading tar: ./res/around-the-corner.ogg
Couldn't find ./res/around-the-corner.ogg in bundle, falling back.
dome: src/engine/audio.c:146: AUDIO_allocate: Assertion `data->length != UINT32_MAX' failed.
Aborted

Add an option to fully rotate a drawable

In ImageData transform for "angle" instead of making it round to 90 degrees, have the image just rotate to whatever degree you put in angle. Or if that can't be done for reasons maybe make another method in Drawable to allow for rotation.
Or not I don't know how difficult it would be to put in, do what you want.

AudioEngine names must be lowercase

The name assigned to a file in AudioEngine has to be only lowercase characters (I didn't try any special characters). At least, this is what it looks like to me :p

This isn't a problem, per se, but it should be documented.

Memory leaks

Valgrind reports a couple of memory leaks:

==336== 24 bytes in 1 blocks are definitely lost in loss record 18 of 214
==336==    at 0x4C2FA3F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==336==    by 0x4C31D84: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==336==    by 0x13E462: wrenMakeHandle (in /home/brian/wren-dome/dome)
==336==    by 0x13A139: ASYNCOP_allocate (io.c:19)
==336==    by 0x13F4DE: runInterpreter (in /home/brian/wren-dome/dome)
==336==    by 0x13D38E: main (main.c:172)

==336==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==336==    by 0x1386CC: ENGINE_readFile (engine.c:53)
==336==    by 0x13A4DC: FILESYSTEM_loadEventHandler (io.c:114)
==336==    by 0x1387B8: ENGINE_taskHandler (engine.c:71)
==336==    by 0x137BE5: ABC_FIFO_executeTask (ABC_fifo.h:150)
==336==    by 0x4EA3D7B: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.8.0)
==336==    by 0x4F18FA8: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.8.0)
==336==    by 0x7C436DA: start_thread (pthread_create.c:463)
==336==    by 0x562D88E: clone (clone.S:95)

==336== 48 bytes in 1 blocks are definitely lost in loss record 67 of 214
==336==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==336==    by 0x1386CC: ENGINE_readFile (engine.c:53)
==336==    by 0x13AADA: AUDIO_allocate (audio.c:120)
==336==    by 0x13F4DE: runInterpreter (in /home/brian/wren-dome/dome)
==336==    by 0x13D38E: main (main.c:172)

==336== 64 bytes in 1 blocks are still reachable in loss record 134 of 214
==336==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==336==    by 0x8078B66: pa_xmalloc (in /usr/lib/x86_64-linux-gnu/pulseaudio/libpulsecommon-11.1.so)
==336==    by 0x8098DB1: pa_memimport_get (in /usr/lib/x86_64-linux-gnu/pulseaudio/libpulsecommon-11.1.so)
==336==    by 0x80A1DE0: ??? (in /usr/lib/x86_64-linux-gnu/pulseaudio/libpulsecommon-11.1.so)
==336==    by 0x80A47D6: ??? (in /usr/lib/x86_64-linux-gnu/pulseaudio/libpulsecommon-11.1.so)
==336==    by 0x5E2C107: pa_mainloop_dispatch (in /usr/lib/x86_64-linux-gnu/libpulse.so.0.20.2)
==336==    by 0x5E2C4DD: pa_mainloop_iterate (in /usr/lib/x86_64-linux-gnu/libpulse.so.0.20.2)
==336==    by 0x4EFD0F5: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.8.0)
==336==    by 0x4EFD51B: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.8.0)
==336==    by 0x4E5D20A: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.8.0)
==336==    by 0x13B03A: AUDIO_ENGINE_allocate (audio.c:200)
==336==    by 0x13F4DE: runInterpreter (in /home/brian/wren-dome/dome)

==336== 552 bytes in 1 blocks are still reachable in loss record 174 of 214
==336==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==336==    by 0x558AE49: __fopen_internal (iofopen.c:65)
==336==    by 0x558AE49: fopen@@GLIBC_2.2.5 (iofopen.c:89)
==336==    by 0x10E521: mtar_open (microtar.c:193)
==336==    by 0x13D06A: main (main.c:118)

==336== 7,344 bytes in 1 blocks are definitely lost in loss record 209 of 214
==336==    at 0x4C31B25: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==336==    by 0x1381B4: readFileFromTar (io.c:19)
==336==    by 0x138647: ENGINE_readFile (engine.c:44)
==336==    by 0x13D08A: main (main.c:119)

==336== 307,200 bytes in 1 blocks are definitely lost in loss record 214 of 214
==336==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==335==    by 0x13D3D8: main (main.c:181)

Serializing an circular object to JSON causes an infinite recursion

Try it:

import "json" for Json

class Game {
  static init() {
    var a = []
    a.add(a)
    System.print(Json.encode(a)) // Causes an infinite recursion
  }
  static update() {}
  static draw(alpha) {}
}

(It is hard to observe this because Wren does nothing when an allocation fails (which is another problem) and the Wren stack is implemented using dynamic allocation, but you can see that by inspecting the process' memory consumption. It should be constant and high).

This is how the same problem is solved in other languages:

  • In JS, a circular json throws a TypeError.
  • In Python, by default, a circular json raises a ValueError, but you can specify check_circular=False and then circles will cause an infinite recursion (and an OverflowError).

It seems that the right approach is to abort the fiber (or return a JsonError, depending on the flag JsonOptions.abortOnError) if a circle is found, maybe with an option to avoid this check in order to speed up serialization (like Python).

GamePad API makes and releases callhandles unnecessarily

The input.GamePad C code makes use of wrenMakeCallHandle, and then almost immediately releases it. Now that we have an INPUT_capture and INPUT_release phase to the module's lifecycle, these handles can be created once and their lifecycle managed appropriately.

[idea] Provide Dome built in class

For simplifying code,
a global class could be created to access the most common dome modules in a single unit.
without need to import it explicitly.

This can be added using the same logic for detecting built in modules such as System.

Current

import "graphics" for Canvas, Color
import "input" for Keyboard
import "dome" for Window

Could be simplified as

Dome.canvas
Dome.color
Dome.input
Dome.window

Example Implementation

// MARK: - Dome
class Input {
  static keyboard {Keyboard}
  static mouse {Mouse}
  static gamepad {GamePad}
}

class Audio {
  static engine {AudioEngine}
  static channel {AudioChannel}
  static state {AudioState}
}

class Graphics {
  static canvas {Canvas}
  static color {Color}
  static image {ImageData}
  static point {Point}
  static drawable {Drawable}
}

class Dome {
  static window {Window}
  static process {Process}
  static canvas {Graphics.canvas}
  static color {Graphics.color}  
  static audio {Audio}
  static io {FileSystem}
  static random {Random}
  static graphics {Graphics}
  static input {Input}
  static font {Font}
  static version {Version}
  static math {Math}
  static vector {Vector}
}

Add separate input checking for pressed / held down button.

Having separate built-in functions like isKeyDown and isKeyPressed for keyboard, mouse button and gamepad would go a long way for helping developers create menus or other UI elements where holding down a button simply does not work.


An example "terminology" would be:

isKeyDown(keycode): Serves the same purpose as the current implementation. Checks for continuous input, useful for movement, etc.

isKeyPressed(keycode, [delay]): Checks if the key is down now, but was not down the previous frame. Another function with a second parameter could implement key repeat with the provided delay. Useful for navigating menus, textboxes, etc.

Would love to hear your thoughts on this!

[bug] Crash when loads random module and exits the game

Describe the bug
I use the random module to generate random points in my game, but, when the game closes, it stops abnormaly, returning the following message into the console:

free(): invalid next size (fast)
Abort (`core' dumped)

To Reproduce

  1. Loads random module
  2. Closes the window or use Process.exit()

Platform and version

  • dome v1.5.0
  • Kubuntu 20.04.1 LTS - amd64

DOME only supports 44.1k sample rate audio

44.1k is a good quality audio (you find it in CDs, for example), but video game audio is often provided at 48k. Trying to play files encoded for 48k results in unusual pitch shifting.

DOME needs to resample the 48k files down to 44.1k, or 44.1k->48k, whichever makes more sense.

Should we be able to support other sample rates?

Remove FFI from the project

DOME has experimental build flags and support for including libFFI, however I've since decided that libFFI is not suitable for DOME, so all that needs to be removed.

You'll need to track down the references to libFFI in the make files, utility build scripts and various macros, in order to remove all the references.

Include zip file support

Currently the engine supports tar files in the form of *.egg files.
I believe the engine could mimic the behaviour of love2d.

you just zip the file in a folder named ย game and put a file named main.wren.
then rename the file mygame.zip to mygame.egg.

mygame.egg
  game/
    main.wren
    other_files....

zip files are easier to work with than tar files, because the main operating systems have native support for it without using the command line or downloading special programs.

here is a simple zip lib. https://github.com/kuba--/zip

:)

Reusable third-party module support

The goal of this issue is to discuss the implementation of something like NodeJS or Python modules, which can be developed and distributed for use across multiple projects with ease.

Any changes to the module-loading system should be backwards compatible with current projects, otherwise we will have to defer it to DOME 2.0.0

I think my own preference would be to extend the .egg/.tar loading system and use that file format for distributing modules.

As far as indicating that part of a module is being imported, I'd expect something like:

import "@domepunk" for PRNG

or, possibly allowing access to sub-files within a module using:

import "@domepunk/sub/path/to/Random" for PRNG

The hard bit is that DOME would need to keep track of which "module context" it was in, in order to resolve modules properly, as well as other rabbit-hole issues.

Include json support

Including support for json files may be handy for reading files created using this format.

Example of a use case.

https://lottiefiles.com/

With that lib you could create animation based on json files. (A parser would have to be implemented though) but the minimum requirement is having json support.

Heres a simple json c implementation
https://github.com/sheredom/json.h

๐Ÿ‘

Font metaclass does not implement 'load(_,_)'

I'm not able to load a font to use for drawing. I'm not too experienced with Wren, but these are the things I've tried to load the font in the same directory as the game:

  • Font.load("monogram", "./monogram.ttf")
  • Canvas.font = "./monogram.ttf"

This gives the error Font metaclass does not implement 'load(_,_)'

I'm not sure if this is me or the docs, but none of these work. I can however see that the load() function in font.wren is static (so is unload()). I'm guessing this makes the functions private, so I'm not able to call them?

Remove use of static fields in examples

Currently the examples use the not-so-pretty double underscore:

import "input" for Keyboard
import "graphics" for Canvas, Color

class Game {

  static init() {
    __x = 10
    __y = 10
    __w = 5
    __h = 5
  }

  static update() {
    if (Keyboard.isKeyDown("left")) {
      __x = __x - 1
    }
    if (Keyboard.isKeyDown("right")) {
      __x = __x + 1
    }
    if (Keyboard.isKeyDown("up")) {
      __y = __y - 1
    }
    if (Keyboard.isKeyDown("down")) {
      __y = __y + 1
    }
  }
  static draw(alpha) {
    Canvas.cls()
    var color = Color.rgb(171, 82, 54)
    Canvas.rectfill(__x, __y, __w, __h, color)
  }
}

It would look better like so:

import "input" for Keyboard
import "graphics" for Canvas, Color

class Main {
  construct new() {}

  init() {
    _x = 10
    _y = 10
    _w = 5
    _h = 5
  }

  update() {
    if (Keyboard.isKeyDown("left")) {
      _x = _x - 1
    }
    if (Keyboard.isKeyDown("right")) {
      _x = _x + 1
    }
    if (Keyboard.isKeyDown("up")) {
      _y = _y - 1
    }
    if (Keyboard.isKeyDown("down")) {
      _y = _y + 1
    }
  }
  draw(alpha) {
    Canvas.cls()
    var color = Color.rgb(171, 82, 54)
    Canvas.rectfill(_x, _y, _w, _h, color)
  }
}

var Game = Main.new()

In cases where variables are created and modified in the init() method, instead of:

init() {
  __position = Vector.new(20, 30)
  
  __position.x = 0 // not sure why you would do this
  __position.y = 0 // but I couldn't come up with a good example
}

update() {
  __position.x = __position.x + 2
}

Then maybe it should be:

init() {
  var position = _position = Vector.new(20, 30)
  
  position.x = 0
  position.y = 0
}

update() {
  _position.x = _position.x + 2
}

I can start changing the docs and examples to this syntax if wanted.

Allow DOME to create folders

Proposed API:
FileSystem.createDirectory(path) would behave like mkdir -p on unix systems, where any missing folders are created on the way.

It should Fiber.abort if the directory couldn't be created for some reason.

SDL moved to GitHub

SDL moved to GitHub on February 10th 2021, so the build system needs to be changed to account for this.

build failing

I'm trying to 'make' the project on Debian Buster using clang 8.0.1. I've never seen this error before:

darkoverlordofdata@penguin:~/GitHub/dome$ make
cd src/util && ./generateEmbedModules.sh
./setup_wren.sh WREN_OPT_RANDOM=1 WREN_OPT_META=1
make[1]: Entering directory '/home/darkoverlordofdata/GitHub/dome/src/lib/wren'
make[1]: Leaving directory '/home/darkoverlordofdata/GitHub/dome/src/lib/wren'
make[1]: Entering directory '/home/darkoverlordofdata/GitHub/dome/src/lib/wren'
make[2]: Entering directory '/home/darkoverlordofdata/GitHub/dome/src/lib/wren'
       str src/vm/wren_core.wren          
       str src/optional/wren_opt_meta.wren 
       str src/optional/wren_opt_random.wren 
        cc src/optional/wren_opt_meta.c    -O0 -DDEBUG -g -std=c99 -fPIC
        cc src/optional/wren_opt_random.c  -O0 -DDEBUG -g -std=c99 -fPIC
        cc src/vm/wren_utils.c             -O0 -DDEBUG -g -std=c99 -fPIC
        cc src/vm/wren_compiler.c          -O0 -DDEBUG -g -std=c99 -fPIC
        cc src/vm/wren_core.c              -O0 -DDEBUG -g -std=c99 -fPIC
        cc src/vm/wren_value.c             -O0 -DDEBUG -g -std=c99 -fPIC
        cc src/vm/wren_debug.c             -O0 -DDEBUG -g -std=c99 -fPIC
        cc src/vm/wren_vm.c                -O0 -DDEBUG -g -std=c99 -fPIC
        cc src/vm/wren_primitive.c         -O0 -DDEBUG -g -std=c99 -fPIC
        cc lib/libwrend.so                 -O0 -DDEBUG -g -std=c99 -fPIC -Wl,-soname,libwren.so
        ar lib/libwrend.a                 rcu
ar: `u' modifier ignored since `D' is the default (see `U')
make[2]: Leaving directory '/home/darkoverlordofdata/GitHub/dome/src/lib/wren'
make[1]: Leaving directory '/home/darkoverlordofdata/GitHub/dome/src/lib/wren'
make[1]: Entering directory '/home/darkoverlordofdata/GitHub/dome/src/lib/wren'
make[1]: Leaving directory '/home/darkoverlordofdata/GitHub/dome/src/lib/wren'
make[1]: Entering directory '/home/darkoverlordofdata/GitHub/dome/src/lib/wren'
make[2]: Entering directory '/home/darkoverlordofdata/GitHub/dome/src/lib/wren'
        cc src/optional/wren_opt_meta.c    -O3 -std=c99 -fPIC
        cc src/optional/wren_opt_random.c  -O3 -std=c99 -fPIC
        cc src/vm/wren_utils.c             -O3 -std=c99 -fPIC
        cc src/vm/wren_compiler.c          -O3 -std=c99 -fPIC
        cc src/vm/wren_core.c              -O3 -std=c99 -fPIC
        cc src/vm/wren_value.c             -O3 -std=c99 -fPIC
        cc src/vm/wren_debug.c             -O3 -std=c99 -fPIC
        cc src/vm/wren_vm.c                -O3 -std=c99 -fPIC
        cc src/vm/wren_primitive.c         -O3 -std=c99 -fPIC
        cc lib/libwren.so                  -O3 -std=c99 -fPIC -Wl,-soname,libwren.so
        ar lib/libwren.a                  rcu
ar: `u' modifier ignored since `D' is the default (see `U')
make[2]: Leaving directory '/home/darkoverlordofdata/GitHub/dome/src/lib/wren'
make[1]: Leaving directory '/home/darkoverlordofdata/GitHub/dome/src/lib/wren'
cp src/lib/wren/src/include/wren.h src/include/wren.h
Makefile:123: release
cc -DHASH="\"9628c37\"" -DWREN_OPT_RANDOM=1 -DWREN_OPT_META=1 -std=c99 -pedantic -Wall  -Wextra -Wno-unused-parameter -Wno-unused-function -Wno-unused-value `which sdl2-config 1>/dev/null && sdl2-config --cflags` -O3 -Wno-discarded-qualifiers -Wno-clobbered --no-pie src/main.c -o dome -Lsrc/lib `sdl2-config --libs` -lm -lwren -isystem src/include
In file included from src/modules/modules.inc:3,
                 from src/modules/map.c:1,
                 from src/main.c:111:
src/modules/graphics.wren.inc:370:1: warning: string length โ€˜8637โ€™ is greater than the length โ€˜4095โ€™ ISO C99 compilers are required to support [-Woverlength-strings]
 "";
 ^~
In file included from src/modules/modules.inc:6,
                 from src/modules/map.c:1,
                 from src/main.c:111:
src/modules/audio.wren.inc:245:1: warning: string length โ€˜5436โ€™ is greater than the length โ€˜4095โ€™ ISO C99 compilers are required to support [-Woverlength-strings]
 "";
 ^~
/usr/bin/ld: /tmp/ccgEYr73.o: relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a PIE object; recompile with -fPIC
/usr/bin/ld: final link failed: nonrepresentable section on output
collect2: error: ld returned 1 exit status
make: *** [Makefile:122: dome] Error 1
darkoverlordofdata@penguin:~/GitHub/dome$ 

2D drawing - Thicker lines

This isn't an issue as such but I thought you might be interested to know that I've been using DOME to successfully create some fancy 2D static images. Basically, I just do all the drawing from the init() method or from methods called by it. I leave the update() and draw() methods empty.

It might be worth mentioning in your blurb that this is possible as it may widen the project's appeal.

One thing that would be useful for future versions is to be able to draw lines etc. with a different thickness than one pixel. At present, I just draw the line the required number of times after offsetting the start and end co-ordinates appropriately.

Delayed audio playback on Linux

Sound effects seem to have about a ~1s delay on my Linux machine, even after extensive tweaking of PulseAudio settings. That delay is much less noticeable on Windows, probably around ~0.25s or less. Further investigation is needed to determine if this happens on other boxes or platforms.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.