├── doc ├── site │ ├── _ext │ │ └── sphinx-lua │ │ │ ├── src │ │ │ ├── .gitignore │ │ │ └── redjack │ │ │ │ ├── __init__.py │ │ │ │ └── sphinx │ │ │ │ └── __init__.py │ │ │ ├── MANIFEST.in │ │ │ ├── setup.cfg │ │ │ └── setup.py │ ├── _static │ │ └── logo.png │ ├── tutorials │ │ ├── arial.ttf │ │ ├── basics_black.png │ │ ├── basics_board.png │ │ ├── basics_final.gif │ │ ├── spritesheet.png │ │ ├── basics_gameover.png │ │ └── basics_sprites.png │ ├── tutorials.rst │ └── resources.rst ├── README.md └── man │ ├── drystal.xsl │ └── CMakeLists.txt ├── tests ├── audio │ ├── random │ │ ├── drystal.cfg │ │ ├── coin1.wav │ │ ├── coin2.wav │ │ ├── hurt1.wav │ │ ├── jump1.wav │ │ ├── jump2.wav │ │ ├── select1.wav │ │ └── main.lua │ ├── test.ogg │ ├── test.wav │ ├── create.lua │ └── play.lua ├── font │ ├── arial.ttf │ ├── parser.lua │ ├── line.lua │ ├── simple_draw.lua │ └── position.lua ├── graphics │ ├── npot.png │ ├── tex.png │ ├── arial.ttf │ ├── image.png │ ├── precise.png │ ├── spritesheet.png │ ├── regressions │ │ ├── arial.ttf │ │ └── font_draw_from.lua │ ├── title.lua │ ├── line.lua │ ├── npot.lua │ ├── read.lua │ ├── fullscreen.lua │ ├── colors.lua │ ├── resize │ │ └── resizable.lua │ ├── draw_point.lua │ ├── draw_polygon.lua │ ├── image.json │ ├── sprites.lua │ ├── filter.lua │ ├── fx.lua │ ├── shaders.lua │ ├── precise.lua │ ├── buffer.lua │ ├── camera.lua │ └── surface_manipulations.lua ├── particle │ ├── squish2.wav │ ├── spritesheet.png │ ├── fire.lua │ ├── blood.lua │ ├── smoke.lua │ └── simple.lua ├── misc │ ├── dir │ │ └── livecode2.lua │ ├── fps.lua │ ├── engine_stop.lua │ ├── objects.lua │ ├── livecode.lua │ └── compute_perf.lua ├── drystal.cfg ├── web │ ├── js.lua │ └── wget.lua ├── event │ ├── pointer.lua │ ├── unicode.lua │ ├── hooks.lua │ └── relative.lua ├── physics │ └── destroy.lua └── index.html ├── external ├── stb_truetype.h ├── miniz.h ├── cjson-fpconv.patch ├── zlibCMakeLists.cmake ├── libpngCMakeLists.cmake └── wavloader.c ├── spec ├── 32x32.png ├── 40x40.png ├── bad_32x32.png ├── storage_spec.moon ├── display_spec.moon ├── audio_spec.moon ├── color_spec.moon ├── tools.moon └── camera_spec.moon ├── tools ├── busted ├── CMakeLists.txt ├── unittest.lua ├── drystal.supp └── setup_busted.sh ├── .gitignore ├── misc └── shell-completion │ └── zsh │ ├── CMakeLists.txt │ ├── _drystal │ └── _drystaljs ├── .gitmodules ├── src ├── font │ ├── api.h │ ├── font_bind.h │ ├── api.c │ ├── parser.h │ ├── font.h │ └── font_bind.c ├── web │ ├── api.h │ ├── web_bind.h │ ├── web.h │ ├── web.lua │ ├── api.c │ ├── web_bind.c │ └── web.c ├── audio │ ├── api.h │ ├── audio_bind.h │ ├── sound_bind.h │ ├── music_bind.h │ ├── sound.h │ ├── api.c │ ├── audio_bind.c │ ├── music.h │ └── audio.h ├── event │ ├── api.h │ ├── event_bind.h │ ├── event_bind.c │ ├── api.c │ └── event.h ├── utils │ ├── api.h │ └── api.c ├── particle │ ├── api.h │ ├── particle.h │ ├── particle.c │ ├── api.c │ ├── system_bind.h │ ├── particle.lua │ └── system.h ├── storage │ ├── api.h │ ├── storage.h │ ├── storage_bind.h │ ├── api.c │ └── storage_bind.c ├── graphics │ ├── api.h │ ├── camera_bind.h │ ├── shader_bind.h │ ├── buffer_bind.h │ ├── camera.h │ ├── opengl_util.h │ ├── opengl_util.c │ ├── display_bind.h │ ├── shader.h │ ├── sprite.lua │ ├── camera.c │ ├── shader_bind.c │ ├── surface.h │ ├── buffer_bind.c │ └── camera_bind.c ├── physics │ ├── api.hpp │ ├── raycast.lua │ ├── shape_bind.hpp │ ├── world_bind.hpp │ ├── body_bind.hpp │ └── joint_bind.hpp ├── luafiles.h ├── livecoding.h ├── engine.h ├── dlua.h ├── lua_util.c ├── log.h ├── log.c ├── build.h ├── drystal.lua ├── macro.h ├── util.h └── module.h ├── Makefile ├── cmake ├── BuildCoverage.cmake ├── GenerateLuaFiles.cmake └── Utils.cmake └── CMakeLists.txt /doc/site/_ext/sphinx-lua/src/.gitignore: -------------------------------------------------------------------------------- 1 | sphinx_lua.egg-info 2 | -------------------------------------------------------------------------------- /tests/audio/random/drystal.cfg: -------------------------------------------------------------------------------- 1 | [.] 2 | *.lua 3 | wget=*.wav 4 | -------------------------------------------------------------------------------- /doc/site/_ext/sphinx-lua/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include RELEASE-VERSION 2 | -------------------------------------------------------------------------------- /doc/site/_ext/sphinx-lua/setup.cfg: -------------------------------------------------------------------------------- 1 | [egg_info] 2 | tag_date = false 3 | -------------------------------------------------------------------------------- /external/stb_truetype.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "stb_truetype.c" 4 | -------------------------------------------------------------------------------- /spec/32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/spec/32x32.png -------------------------------------------------------------------------------- /spec/40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/spec/40x40.png -------------------------------------------------------------------------------- /spec/bad_32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/spec/bad_32x32.png -------------------------------------------------------------------------------- /tools/busted: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ./tools/runner.py -r unittest -- $@ 4 | 5 | -------------------------------------------------------------------------------- /tests/audio/test.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/tests/audio/test.ogg -------------------------------------------------------------------------------- /tests/audio/test.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/tests/audio/test.wav -------------------------------------------------------------------------------- /tests/font/arial.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/tests/font/arial.ttf -------------------------------------------------------------------------------- /tests/graphics/npot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/tests/graphics/npot.png -------------------------------------------------------------------------------- /tests/graphics/tex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/tests/graphics/tex.png -------------------------------------------------------------------------------- /doc/site/_static/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/doc/site/_static/logo.png -------------------------------------------------------------------------------- /tests/graphics/arial.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/tests/graphics/arial.ttf -------------------------------------------------------------------------------- /tests/graphics/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/tests/graphics/image.png -------------------------------------------------------------------------------- /doc/site/tutorials/arial.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/doc/site/tutorials/arial.ttf -------------------------------------------------------------------------------- /tests/audio/random/coin1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/tests/audio/random/coin1.wav -------------------------------------------------------------------------------- /tests/audio/random/coin2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/tests/audio/random/coin2.wav -------------------------------------------------------------------------------- /tests/audio/random/hurt1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/tests/audio/random/hurt1.wav -------------------------------------------------------------------------------- /tests/audio/random/jump1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/tests/audio/random/jump1.wav -------------------------------------------------------------------------------- /tests/audio/random/jump2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/tests/audio/random/jump2.wav -------------------------------------------------------------------------------- /tests/graphics/precise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/tests/graphics/precise.png -------------------------------------------------------------------------------- /tests/particle/squish2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/tests/particle/squish2.wav -------------------------------------------------------------------------------- /tests/audio/random/select1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/tests/audio/random/select1.wav -------------------------------------------------------------------------------- /tests/graphics/spritesheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/tests/graphics/spritesheet.png -------------------------------------------------------------------------------- /tests/particle/spritesheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/tests/particle/spritesheet.png -------------------------------------------------------------------------------- /doc/site/tutorials/basics_black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/doc/site/tutorials/basics_black.png -------------------------------------------------------------------------------- /doc/site/tutorials/basics_board.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/doc/site/tutorials/basics_board.png -------------------------------------------------------------------------------- /doc/site/tutorials/basics_final.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/doc/site/tutorials/basics_final.gif -------------------------------------------------------------------------------- /doc/site/tutorials/spritesheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/doc/site/tutorials/spritesheet.png -------------------------------------------------------------------------------- /doc/site/tutorials/basics_gameover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/doc/site/tutorials/basics_gameover.png -------------------------------------------------------------------------------- /doc/site/tutorials/basics_sprites.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/doc/site/tutorials/basics_sprites.png -------------------------------------------------------------------------------- /tests/graphics/regressions/arial.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kidanger/Drystal/HEAD/tests/graphics/regressions/arial.ttf -------------------------------------------------------------------------------- /tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(GNUInstallDirs) 2 | install(PROGRAMS drystaljs.py DESTINATION ${CMAKE_INSTALL_BINDIR} RENAME drystaljs) 3 | 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build-*/ 2 | /web 3 | *.pyc 4 | *.swp 5 | /doc/site/_build/ 6 | /tests/storage/.storage 7 | .luarocks 8 | .rocks 9 | .storage 10 | 11 | -------------------------------------------------------------------------------- /tests/misc/dir/livecode2.lua: -------------------------------------------------------------------------------- 1 | local L = { 2 | value=1, 3 | } 4 | L.__index = L 5 | 6 | function L.new() 7 | return setmetatable({}, L) 8 | end 9 | 10 | return L 11 | 12 | -------------------------------------------------------------------------------- /external/miniz.h: -------------------------------------------------------------------------------- 1 | #define MINIZ_HEADER_FILE_ONLY 2 | #define MINIZ_NO_ARCHIVE_WRITING_APIS 3 | #define MINIZ_NO_TIME 4 | #define MINIZ_NO_ZLIB_COMPATIBLE_NAMES 5 | #include "miniz.c" 6 | -------------------------------------------------------------------------------- /misc/shell-completion/zsh/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | install(FILES "_drystal" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/zsh/site-functions/") 2 | install(FILES "_drystaljs" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/zsh/site-functions/") 3 | -------------------------------------------------------------------------------- /tests/graphics/title.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | function drystal.init() 4 | drystal.resize(400, 300) 5 | end 6 | 7 | local time = 0 8 | 9 | function drystal.update(dt) 10 | time = time + dt 11 | drystal.set_title(time) 12 | end 13 | -------------------------------------------------------------------------------- /tests/drystal.cfg: -------------------------------------------------------------------------------- 1 | [options] 2 | version = prerelease 3 | destination = web 4 | zip = game.zip 5 | html = index.html 6 | htmltemplate = index.html 7 | arguments = 8 | 9 | [*] 10 | *.lua 11 | *.png 12 | *.ttf 13 | *.json 14 | *.ogg 15 | *.wav 16 | -------------------------------------------------------------------------------- /doc/README.md: -------------------------------------------------------------------------------- 1 | Documentation build 2 | ------------------- 3 | 4 | First, you need sphinx and pip (python2) then, as root, run: 5 | 6 | pip install sphinx_rtd_theme 7 | 8 | If you want to build the documentation in HTML go to doc/site/ and run: 9 | 10 | make html 11 | -------------------------------------------------------------------------------- /doc/site/tutorials.rst: -------------------------------------------------------------------------------- 1 | Tutorials 2 | ========= 3 | 4 | Here is a list of tutorials that will teach you how to use Drystal by creating games. We start with a basic 5 | tic-tac-toe, then we create a space invader and finally a plateformer. 6 | 7 | .. toctree:: 8 | 9 | tutorials/basics.rst 10 | 11 | -------------------------------------------------------------------------------- /tests/misc/fps.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | function drystal.init() 4 | drystal.resize(400, 400) 5 | end 6 | 7 | function drystal.update(dt) 8 | print(1/dt, dt) 9 | end 10 | 11 | function drystal.key_press(key) 12 | if key == 'a' then 13 | drystal.stop() 14 | end 15 | end 16 | 17 | -------------------------------------------------------------------------------- /tests/web/js.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | drystal.run_js [[ 4 | document.title = "Drystal js.lua"; 5 | document.body.style.backgroundColor = "red"; 6 | window.alert("hello from drystal"); 7 | ]] 8 | 9 | print(drystal.run_js [[ 10 | "lol"; 11 | ]]) 12 | 13 | drystal.stop() 14 | 15 | -------------------------------------------------------------------------------- /misc/shell-completion/zsh/_drystal: -------------------------------------------------------------------------------- 1 | #compdef drystal 2 | 3 | _arguments \ 4 | {-h,--help}'[Show this help message and exit]' \ 5 | {-v,--version}'[Show Drystal version and available features]' \ 6 | {-l,--livecoding}'[Enable the livecoding which will reload the lua code when modifications on the files are performed]' \ 7 | '1::Lua file:_files' 8 | -------------------------------------------------------------------------------- /tests/misc/engine_stop.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | print 'should print: Exiting' 4 | function drystal.init() 5 | print 'should not be printed' 6 | end 7 | 8 | function drystal.update(dt) 9 | end 10 | 11 | function drystal.draw() 12 | end 13 | 14 | function drystal.atexit() 15 | print 'Exiting' 16 | end 17 | 18 | drystal.stop() 19 | 20 | -------------------------------------------------------------------------------- /tools/unittest.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env drystal 2 | 3 | package.path = './.rocks/share/lua/5.3/?.lua;./.rocks/share/lua/5.3/?/init.lua;' .. package.path 4 | package.cpath = './.rocks/lib/lua/5.3/?.so;' .. package.cpath 5 | 6 | require 'moonscript' 7 | require 'spec.tools' 8 | 9 | require 'busted.runner' { 10 | standalone=false, 11 | } 12 | 13 | drystal = require 'drystal' 14 | drystal.stop() 15 | 16 | -------------------------------------------------------------------------------- /tests/graphics/line.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | drystal.resize(600, 400) 4 | 5 | local mx = 0 6 | local my = 0 7 | 8 | function drystal.draw() 9 | drystal.set_color(0, 0, 0) 10 | drystal.draw_background() 11 | 12 | drystal.set_color(255, 255, 255) 13 | drystal.draw_line(300, 200, mx, my, 6) 14 | end 15 | 16 | function drystal.mouse_motion(x, y) 17 | mx = x 18 | my = y 19 | end 20 | -------------------------------------------------------------------------------- /doc/site/_ext/sphinx-lua/src/redjack/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ---------------------------------------------------------------------- 3 | # Copyright © 2012, RedJack, LLC. 4 | # All rights reserved. 5 | # 6 | # Please see the LICENSE.txt file in this distribution for license 7 | # details. 8 | # ---------------------------------------------------------------------- 9 | 10 | __import__('pkg_resources').declare_namespace(__name__) 11 | -------------------------------------------------------------------------------- /tools/drystal.supp: -------------------------------------------------------------------------------- 1 | { 2 | xorg_modules 3 | Memcheck:Leak 4 | ... 5 | obj:/usr/lib/xorg/modules/dri/*.so 6 | ... 7 | } 8 | { 9 | mesa 10 | Memcheck:Leak 11 | ... 12 | obj:/usr/lib/mesa/*.so* 13 | ... 14 | } 15 | { 16 | X11 17 | Memcheck:Leak 18 | ... 19 | obj:/usr/lib/libX11.so* 20 | ... 21 | } 22 | { 23 | alsa 24 | Memcheck:Leak 25 | ... 26 | obj:/usr/lib/libasound.so* 27 | ... 28 | } 29 | 30 | -------------------------------------------------------------------------------- /doc/site/_ext/sphinx-lua/src/redjack/sphinx/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ---------------------------------------------------------------------- 3 | # Copyright © 2012, RedJack, LLC. 4 | # All rights reserved. 5 | # 6 | # Please see the LICENSE.txt file in this distribution for license 7 | # details. 8 | # ---------------------------------------------------------------------- 9 | 10 | __import__('pkg_resources').declare_namespace(__name__) 11 | -------------------------------------------------------------------------------- /tests/misc/objects.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | local s = drystal.screen 4 | 5 | s.x = 4 6 | assert(s.x == 4) 7 | assert(s.draw_on ~= nil) 8 | assert(getmetatable(s).draw_on ~= nil) 9 | assert(s.__self == s) 10 | 11 | assert(getmetatable(getmetatable(s)) == drystal.Surface) 12 | assert(getmetatable(getmetatable(s)).draw_on ~= nil) 13 | 14 | for k, v in pairs(getmetatable(s)) do 15 | print(k, v) 16 | end 17 | 18 | drystal.stop() 19 | 20 | -------------------------------------------------------------------------------- /doc/man/drystal.xsl: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 1 9 | 0 10 | 0 11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/font/parser.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | math.randomseed(os.time()) 3 | 4 | local font = assert(drystal.load_font('arial.ttf', 20)) 5 | 6 | function gen() 7 | local text = '' 8 | local chars = "{}|r:9" 9 | for i = 1, math.random(30) do 10 | local r =math.random(#chars) 11 | text = text .. chars:sub(r, r) 12 | end 13 | return text 14 | end 15 | 16 | for i = 1, 100 do 17 | local text = gen() 18 | print(text, font:sizeof(text)) 19 | end 20 | 21 | drystal.stop() 22 | 23 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "external/lua"] 2 | path = external/lua 3 | url = https://github.com/kidanger/lua-5.3.git 4 | [submodule "external/lua-cjson"] 5 | path = external/lua-cjson 6 | url = https://github.com/mpx/lua-cjson.git 7 | [submodule "external/box2d"] 8 | path = external/box2d 9 | url = https://github.com/ansman/box2d.git 10 | [submodule "external/libpng"] 11 | path = external/libpng 12 | url = https://github.com/glennrp/libpng.git 13 | [submodule "external/zlib"] 14 | path = external/zlib 15 | url = https://github.com/madler/zlib 16 | -------------------------------------------------------------------------------- /tests/graphics/npot.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | function drystal.init() 4 | drystal.resize(300, 200) 5 | surf = assert(drystal.load_surface('npot.png')) 6 | local w, h = surf.w, surf.h 7 | 8 | assert(w == 200, 'width is not 200, ' .. w) 9 | assert(h == 150, 'height is not 150, ' .. h) 10 | surf:draw_from() 11 | end 12 | 13 | function drystal.draw() 14 | local sprite = {x=0,y=0,w=200,h=150} 15 | drystal.draw_sprite(sprite, 0, 0) 16 | end 17 | 18 | function drystal.key_press(k) 19 | if k == 'a' then 20 | drystal.stop() 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /tests/web/wget.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | local function onsuccess(filename) 4 | print(filename, 'wgetted!') 5 | print(io.open(filename):read('*all')) 6 | end 7 | 8 | local function onerror(filename) 9 | print(filename, 'ko') 10 | end 11 | 12 | function drystal.init() 13 | print(drystal.is_web) 14 | drystal.wget('/', 'f1', onsuccess, onerror) 15 | drystal.wget('src/log.hpp', 'f2', onsuccess, onerror) 16 | drystal.wget('http://google.fr', 'f3', onsuccess, onerror) 17 | print 'boom' 18 | end 19 | 20 | function drystal.update() 21 | drystal.stop() 22 | end 23 | 24 | -------------------------------------------------------------------------------- /tests/misc/livecode.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | local L = require 'dir.livecode2' 3 | 4 | drystal.resize(300, 200) 5 | 6 | local l = L.new() 7 | print('value:', l.value) 8 | 9 | local old 10 | local time = 0 11 | function drystal.update(dt) 12 | time = time + dt 13 | if old ~= l.value then 14 | print(old, '->', l.value) 15 | old = l.value 16 | end 17 | if time > 1 then 18 | time = time - 1 19 | print('ping', dt) 20 | end 21 | end 22 | 23 | function drystal.key_press(k) 24 | if k == 'a' then 25 | drystal.stop() 26 | elseif k == 'x' then 27 | drystal.reload() 28 | end 29 | end 30 | 31 | -------------------------------------------------------------------------------- /spec/storage_spec.moon: -------------------------------------------------------------------------------- 1 | drystal = require 'drystal' 2 | 3 | describe 'storage', -> 4 | 5 | it 'stores data', -> 6 | drystal.store 'test_storage', {text:'blabla', duck:58} 7 | data = drystal.fetch 'test_storage' 8 | assert.same {text:'blabla', duck:58}, data 9 | 10 | it 'overwrites previous stored data', -> 11 | drystal.store 'test_storage', {text:'blabla', duck:58} 12 | drystal.store 'test_storage', {text:'foobar', duck:59} 13 | data = drystal.fetch 'test_storage' 14 | assert.same {text:'foobar', duck:59}, data 15 | 16 | it 'does not contain unknown keys', -> 17 | data = drystal.fetch 'unknown' 18 | assert.nil data 19 | 20 | -------------------------------------------------------------------------------- /tests/event/pointer.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | function drystal.init() 4 | drystal.resize(400, 400) 5 | print 'Press h to hide, r to set relative mode' 6 | end 7 | 8 | local relative = false 9 | local hidden = false 10 | function drystal.key_press(key) 11 | if key == 'a' then 12 | drystal.stop() 13 | elseif key == 'h' then 14 | hidden = not hidden 15 | drystal.show_cursor(not hidden) 16 | elseif key == 'r' then 17 | relative = not relative 18 | drystal.set_relative_mode(relative) 19 | end 20 | print('relative:', relative, 'hide:', hidden) 21 | end 22 | 23 | function drystal.mouse_motion(x, y, dx, dy) 24 | print(x, y, dx, dy) 25 | end 26 | -------------------------------------------------------------------------------- /doc/site/_ext/sphinx-lua/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from setuptools import setup, find_packages 4 | 5 | from version import get_git_version 6 | 7 | try: 8 | import setuptools_git 9 | except ImportError: 10 | print("WARNING!") 11 | print("We need the setuptools-git package to be installed for") 12 | print("some of the setup.py targets to work correctly.") 13 | 14 | PACKAGE = 'sphinx-lua' 15 | VERSION = get_git_version() 16 | 17 | setup( 18 | name = PACKAGE, 19 | version = VERSION, 20 | package_dir = {'': 'src'}, 21 | packages = find_packages('src'), 22 | namespace_packages = ['redjack', 'redjack.sphinx'], 23 | install_requires = ['Sphinx'], 24 | ) 25 | -------------------------------------------------------------------------------- /tests/graphics/read.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | local image 4 | 5 | function drystal.init() 6 | drystal.resize(600, 400) 7 | image = drystal.load_surface('tex.png') 8 | end 9 | 10 | function drystal.draw() 11 | drystal.set_color(0, 0, 0) 12 | drystal.set_alpha(255) 13 | drystal.draw_background() 14 | 15 | local radius = 3 16 | for x = 1, image.w do 17 | for y = 1, image.h do 18 | local r, g, b, a = image:get_pixel(x, y) 19 | drystal.set_color(r, g, b) 20 | drystal.set_alpha(a) 21 | drystal.draw_point(x * radius, y * radius, radius) 22 | end 23 | end 24 | end 25 | 26 | function drystal.key_press(k) 27 | if k == 'a' then 28 | drystal.stop() 29 | end 30 | end 31 | 32 | -------------------------------------------------------------------------------- /spec/display_spec.moon: -------------------------------------------------------------------------------- 1 | drystal = require 'drystal' 2 | 3 | describe 'display', -> 4 | 5 | before_each -> 6 | drystal.set_alpha 255 7 | drystal.set_color 'black' 8 | drystal.screen\draw_on! 9 | drystal.draw_background! 10 | 11 | it 'can resize', -> 12 | drystal.resize 120, 100 13 | assert.equals 120, drystal.screen.w 14 | assert.equals 100, drystal.screen.h 15 | 16 | drystal.resize 150, 110 17 | assert.equals 150, drystal.screen.w 18 | assert.equals 110, drystal.screen.h 19 | 20 | it 'draws lines', -> 21 | drystal.set_color 'red' 22 | drystal.draw_line 10, 10, 20, 10 23 | for i = 11, 20 24 | assert.color drystal.screen, i, 10, 'red' 25 | assert.color drystal.screen, i, 11, 'black' 26 | 27 | -------------------------------------------------------------------------------- /tests/graphics/fullscreen.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | drystal.resize(800, 600) 4 | function drystal.draw(dt) 5 | drystal.set_alpha(255) 6 | drystal.set_color(255, 25, 255) 7 | drystal.draw_background() 8 | 9 | drystal.set_color(255, 0, 0) 10 | drystal.draw_rect(50, 50, drystal.screen.w - 100, drystal.screen.h - 100) 11 | end 12 | 13 | local full = false 14 | function drystal.key_press(k) 15 | if k == 'f' then 16 | full = true 17 | drystal.set_fullscreen(true) 18 | elseif k == 'g' then 19 | full = false 20 | drystal.set_fullscreen(false) 21 | end 22 | end 23 | 24 | function drystal.page_resize(w, h) 25 | print(w, h) 26 | if full then 27 | drystal.set_fullscreen(true) 28 | end 29 | end 30 | 31 | -------------------------------------------------------------------------------- /tests/graphics/regressions/font_draw_from.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | drystal.resize(600, 400) 4 | 5 | local x, y = 0, 0 6 | local font = assert(drystal.load_font('arial.ttf', 25)) 7 | local text = 'all fine!' 8 | local surface = drystal.new_surface(font:sizeof(text)) 9 | local sprite = drystal.new_sprite({x=0, y=0, w=surface.w, h=surface.h}, x, y) 10 | sprite.angle = math.pi * 2 11 | 12 | function drystal.draw() 13 | collectgarbage() 14 | drystal.set_color(250, 20, 20) 15 | drystal.set_alpha(255) 16 | drystal.draw_background() 17 | 18 | local screen = surface:draw_on() 19 | drystal.set_color(0, 0, 0) 20 | font:draw(text, 0, 0) 21 | surface:draw_from() 22 | screen:draw_on() 23 | 24 | sprite:draw() 25 | end 26 | -------------------------------------------------------------------------------- /tests/graphics/colors.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | local color = drystal.colors['#22DD22'] 4 | 5 | function drystal.init() 6 | drystal.resize(600, 400) 7 | print('press d or l or m or a') 8 | end 9 | 10 | function drystal.update(dt) 11 | end 12 | 13 | function drystal.draw() 14 | drystal.set_color(color) 15 | drystal.draw_background() 16 | 17 | drystal.set_color 'cyan' 18 | drystal.draw_rect(20, 20, 40, 40) 19 | end 20 | 21 | function drystal.key_press(key) 22 | if key == 'd' then 23 | color = color:darker() 24 | end 25 | if key == 'l' then 26 | color = color:lighter() 27 | end 28 | if key == 'm' then 29 | color = color * drystal.colors.steelblue 30 | end 31 | if key == 'a' then 32 | color = color + drystal.colors.red 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /tests/font/line.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | drystal.resize(600, 400) 4 | 5 | local font = assert(drystal.load_font('arial.ttf', 20)) 6 | 7 | local text = [[blba 8 | dsqdsq dsq 9 | k{g:40|??{outr:80|outline|ds}lol}qj dk{r:50|sq 10 | ds}qj dksq 11 | ]] 12 | 13 | function drystal.draw() 14 | drystal.set_color(0, 0, 0) 15 | drystal.draw_background() 16 | 17 | drystal.set_color(255, 255, 255) 18 | 19 | font:draw_plain(text, 10, 10) 20 | drystal.draw_square(10, 10, font:sizeof_plain(text)) 21 | 22 | font:draw(text, 10, 100) 23 | drystal.draw_square(10, 100, font:sizeof(text)) 24 | 25 | font:draw(text, 100, 200, drystal.aligns.center) 26 | drystal.draw_line(100, 200, 100, 300) 27 | font:draw(text, 300, 200, drystal.aligns.right) 28 | drystal.draw_line(300, 200, 300, 300) 29 | end 30 | 31 | -------------------------------------------------------------------------------- /src/font/api.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include "module.h" 20 | 21 | DECLARE_MODULE(font) 22 | 23 | -------------------------------------------------------------------------------- /src/web/api.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include "module.h" 20 | 21 | DECLARE_MODULE(web) 22 | 23 | -------------------------------------------------------------------------------- /src/audio/api.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include "module.h" 20 | 21 | DECLARE_MODULE(audio) 22 | 23 | -------------------------------------------------------------------------------- /src/event/api.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include "module.h" 20 | 21 | DECLARE_MODULE(event) 22 | 23 | -------------------------------------------------------------------------------- /src/utils/api.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include "module.h" 20 | 21 | DECLARE_MODULE(utils) 22 | 23 | -------------------------------------------------------------------------------- /src/particle/api.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include "module.h" 20 | 21 | DECLARE_MODULE(particle) 22 | 23 | -------------------------------------------------------------------------------- /src/storage/api.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include "module.h" 20 | 21 | DECLARE_MODULE(storage) 22 | 23 | -------------------------------------------------------------------------------- /tests/event/unicode.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | function drystal.init() 4 | drystal.resize(400, 400) 5 | end 6 | 7 | function drystal.update() 8 | end 9 | 10 | function drystal.draw() 11 | end 12 | 13 | local text = '' 14 | local texting = false 15 | 16 | function drystal.key_press(key) 17 | print('key_press', key) 18 | if texting then 19 | if key == 'return' then 20 | texting = false 21 | print('=>', text) 22 | end 23 | else 24 | if key == 'i' then 25 | text = '' 26 | texting = true 27 | elseif key == 'a' then 28 | drystal.stop() 29 | end 30 | end 31 | end 32 | function drystal.key_release(key) 33 | print('key_release', key) 34 | end 35 | 36 | function drystal.key_text(str) 37 | if texting then 38 | print('key_text', str) 39 | text = text .. str 40 | print("text =", text) 41 | end 42 | end 43 | 44 | -------------------------------------------------------------------------------- /tests/graphics/resize/resizable.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | local w, h = 600, 400 4 | 5 | function drystal.init() 6 | print('init') 7 | drystal.resize(w, h) 8 | update_surf() 9 | end 10 | 11 | function drystal.draw() 12 | drystal.set_color(255, 255, 255) 13 | drystal.draw_background() 14 | 15 | drystal.set_color(0, 0, 0) 16 | drystal.draw_rect(2, 2, w - 4, h - 4) 17 | end 18 | 19 | function drystal.key_press(key) 20 | if key == 'h' then 21 | w = w - 100 22 | elseif key == 'l' then 23 | w = w + 100 24 | elseif key == 'j' then 25 | h = h + 100 26 | elseif key == 'k' then 27 | h = h - 100 28 | else 29 | return 30 | end 31 | drystal.resize(w, h) 32 | update_surf() 33 | end 34 | 35 | function update_surf() 36 | w, h = drystal.screen.w, drystal.screen.h 37 | print("hjlk to resize, current size is " .. w .. "x" .. h) 38 | end 39 | 40 | -------------------------------------------------------------------------------- /src/event/event_bind.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include 20 | 21 | int mlua_set_relative_mode(lua_State* L); 22 | 23 | -------------------------------------------------------------------------------- /src/web/web_bind.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include 20 | 21 | int mlua_wget(lua_State *L); 22 | int mlua_run_js(lua_State* L); 23 | 24 | -------------------------------------------------------------------------------- /src/graphics/api.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include "module.h" 20 | 21 | DECLARE_MODULE(graphics) 22 | 23 | int graphics_index(lua_State* L); 24 | 25 | -------------------------------------------------------------------------------- /src/storage/storage.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | char* storage_fetch(const char* key); 20 | void storage_store(const char* key, const char* value); 21 | 22 | -------------------------------------------------------------------------------- /src/storage/storage_bind.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include 20 | 21 | int mlua_store(lua_State* L); 22 | int mlua_fetch(lua_State* L); 23 | 24 | -------------------------------------------------------------------------------- /doc/man/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(GNUInstallDirs) 2 | 3 | find_program(MAN_XSLTPROC xsltproc) 4 | if (NOT MAN_XSLTPROC) 5 | message(FATAL_ERROR "Unable to find xsltproc") 6 | endif() 7 | 8 | file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/man1) 9 | 10 | set(MAN_RESOURCES 11 | drystal.xsl 12 | ) 13 | 14 | add_custom_target(man) 15 | install(CODE "EXECUTE_PROCESS(COMMAND ${CMAKE_MAKE_PROGRAM} man)") 16 | function(add_manpage volume title) 17 | add_custom_command(TARGET man 18 | DEPENDS ${title}.${volume}.xml ${MAN_RESOURCES} 19 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 20 | COMMAND ${MAN_XSLTPROC} -nonet --xinclude -o "${CMAKE_CURRENT_BINARY_DIR}/man${volume}/" drystal.xsl ${title}.${volume}.xml 21 | ) 22 | install(FILES "${CMAKE_CURRENT_BINARY_DIR}/man${volume}/${title}.${volume}" DESTINATION "${CMAKE_INSTALL_MANDIR}/man${volume}") 23 | endfunction() 24 | 25 | add_manpage(1 drystal) 26 | 27 | -------------------------------------------------------------------------------- /doc/site/resources.rst: -------------------------------------------------------------------------------- 1 | Resources 2 | ========= 3 | 4 | .. Snippets 5 | .. -------- 6 | 7 | Useful links 8 | ------------ 9 | 10 | Lua 11 | ^^^ 12 | 13 | - `Programming In Lua `_ 14 | - `Lua 5.3 manual `_ 15 | 16 | 17 | Box2D 18 | ^^^^^ 19 | 20 | - `Box2D manual `_ 21 | - `Some Box2D tutorials `_ 22 | 23 | 24 | Lua libraries 25 | ^^^^^^^^^^^^^ 26 | 27 | - `A simple class library `_ 28 | - `Helper utilities `_ made for LÖVE but most can work with Drystal 29 | - `A tweening library `_ 30 | 31 | 32 | Moonscript 33 | ^^^^^^^^^^ 34 | 35 | `Moonscript `_ is a language that compiles to Lua. It can be used to create games with Drystal. 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/audio/audio_bind.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include 20 | 21 | int mlua_set_sound_volume(lua_State *L); 22 | int mlua_set_music_volume(lua_State *L); 23 | 24 | -------------------------------------------------------------------------------- /src/web/web.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #ifdef EMSCRIPTEN 20 | char *run_js(const char* script); 21 | void wget(const char* url, const char* filename); 22 | #endif 23 | 24 | -------------------------------------------------------------------------------- /tests/graphics/draw_point.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | local mx, my = 0, 0 4 | 5 | function drystal.init() 6 | drystal.resize(600, 400) 7 | image = drystal.load_surface('tex.png') 8 | image:draw_from() 9 | end 10 | 11 | local time = 0 12 | function drystal.update(dt) 13 | time = time + dt 14 | end 15 | 16 | function drystal.draw() 17 | drystal.set_color(drystal.colors.white) 18 | drystal.draw_background() 19 | 20 | for y = 0, 400, 8 do 21 | for x = 0, 600, 8 do 22 | local r = math.sin((x + y + time*1000)/100)/2+0.5 23 | drystal.set_color(r*255, 0, 0) 24 | drystal.draw_point(x, y, 8) 25 | end 26 | end 27 | 28 | drystal.set_color(drystal.colors.lime) 29 | drystal.draw_point_tex(0, 0, mx-8, my-8, 15) 30 | end 31 | 32 | function drystal.mouse_motion(x, y) 33 | mx = x 34 | my = y 35 | end 36 | 37 | function drystal.key_press(k) 38 | if k == 'a' then 39 | drystal.stop() 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /tests/misc/compute_perf.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | local W, H = 600, 400 4 | local target = 1 / 60 5 | local number = 100000 6 | local tick = 0 7 | 8 | function drystal.init() 9 | drystal.resize(W, H) 10 | end 11 | 12 | local function compute(n) 13 | local acc = 1 14 | for i = 1, n do 15 | acc = acc * 1.45 + 1/acc 16 | end 17 | return acc 18 | end 19 | 20 | local function compute_int(n) 21 | local acc = 1 22 | for i = 1, n do 23 | acc = acc * 2 - n / 10 24 | end 25 | return acc 26 | end 27 | 28 | function drystal.update(dt) 29 | compute(number) 30 | if tick > 4 then 31 | if dt > target then 32 | number = number * .99 33 | else 34 | number = number * 1.02 35 | end 36 | end 37 | tick = tick + 1 38 | if tick % 60 == 0 then 39 | print(math.floor(number), dt - target) 40 | end 41 | end 42 | 43 | function drystal.key_press(k) 44 | if k == 'a' then 45 | drystal.stop() 46 | end 47 | end 48 | 49 | -------------------------------------------------------------------------------- /src/storage/api.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #include "module.h" 18 | #include "storage_bind.h" 19 | #include "api.h" 20 | 21 | BEGIN_MODULE(storage) 22 | DECLARE_FUNCTION(store) 23 | DECLARE_FUNCTION(fetch) 24 | END_MODULE() 25 | 26 | -------------------------------------------------------------------------------- /tools/setup_busted.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | if [ -z "$1" ]; then 4 | TYPE=Release 5 | else 6 | TYPE=$1 7 | fi 8 | 9 | rm -rf .luarocks 10 | rm -rf .rocks 11 | 12 | ROOT=`pwd` 13 | BUILD=$ROOT/build-native-$TYPE 14 | ROCKVER=2.2.2 15 | 16 | wget https://github.com/keplerproject/luarocks/archive/v${ROCKVER}.tar.gz || exit 1 17 | tar zxpf v${ROCKVER}.tar.gz 18 | rm luarocks-${ROCKVER}.tar.gz 19 | mv luarocks-$ROCKVER .luarocks 20 | 21 | cd .luarocks 22 | sh configure --lua-version=5.3 --with-lua-bin=$BUILD/external --with-lua-include=$ROOT/external/lua/src --prefix=`pwd` --sysconfdir=`pwd`/luarocks --force-config || exit 1 23 | make build || exit 1 24 | make install || exit 1 25 | cd .. 26 | 27 | ./.luarocks/bin/luarocks --tree=.rocks install busted || exit 1 28 | ./.luarocks/bin/luarocks --tree=.rocks install moonscript || exit 1 29 | ./.luarocks/bin/luarocks --tree=.rocks install lua_cliargs 2.5-5 || exit 1 # temporary fix for outdated busted 30 | 31 | -------------------------------------------------------------------------------- /src/physics/api.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #include "module.h" 24 | 25 | DECLARE_MODULE(physics) 26 | 27 | #ifdef __cplusplus 28 | } 29 | #endif 30 | 31 | -------------------------------------------------------------------------------- /src/web/web.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | if drystal.is_web then 4 | drystal.raw_wget = drystal.wget 5 | local wget_requests = {} 6 | 7 | function drystal.on_wget_success(file) 8 | for _, f in ipairs(wget_requests[file].onload) do 9 | f(file) 10 | end 11 | wget_requests[file] = nil 12 | end 13 | function drystal.on_wget_error(file) 14 | for _, f in ipairs(wget_requests[file].onerror) do 15 | f(file) 16 | end 17 | wget_requests[file] = nil 18 | end 19 | 20 | function drystal.wget(url, file, onload, onerror) 21 | assert(onload) 22 | assert(onerror) 23 | 24 | if not drystal.is_web then 25 | return 26 | end 27 | 28 | if wget_requests[file] then 29 | -- already requested 30 | table.insert(wget_requests[file].onload, onload) 31 | table.insert(wget_requests[file].onerror, onerror) 32 | return 33 | end 34 | 35 | drystal.raw_wget(url, file) 36 | wget_requests[file] ={ 37 | onload={onload}, 38 | onerror={onerror}, 39 | } 40 | end 41 | end 42 | 43 | -------------------------------------------------------------------------------- /tests/graphics/draw_polygon.lua: -------------------------------------------------------------------------------- 1 | local drystal = require "drystal" 2 | 3 | local mouse_points = { 4 | } 5 | 6 | function drystal.init() 7 | drystal.resize(600, 400) 8 | end 9 | 10 | function drystal.draw() 11 | drystal.set_alpha(255) 12 | drystal.set_color(255, 255, 255) 13 | drystal.draw_background() 14 | 15 | drystal.set_color(0, 0, 0) 16 | local points = { 17 | 25, 25, 18 | 50, 25, 19 | 75, 50, 20 | 25, 50, 21 | 25, 25 22 | } 23 | 24 | drystal.draw_polygon(unpack(points)) 25 | 26 | drystal.set_color(200, 0, 0) 27 | drystal.draw_polyline(false, 5, unpack(points)) 28 | 29 | if #mouse_points > 2 then 30 | drystal.draw_polygon(unpack(mouse_points)) 31 | drystal.set_color(255, 0, 0) 32 | drystal.draw_polyline(true, unpack(mouse_points)) 33 | end 34 | end 35 | 36 | function drystal.mouse_press(x, y, b) 37 | table.insert(mouse_points, x) 38 | table.insert(mouse_points, y) 39 | end 40 | 41 | function drystal.key_press(key) 42 | if key == 'a' then 43 | drystal.stop() 44 | end 45 | end 46 | 47 | -------------------------------------------------------------------------------- /src/luafiles.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include 20 | 21 | /** 22 | * luafiles.c is generated by CMake at compile time. 23 | * This functions runs .lua files (located in src/) and return 1 if success. 24 | */ 25 | int load_luafiles(lua_State* L, int traceback_index); 26 | 27 | -------------------------------------------------------------------------------- /src/graphics/camera_bind.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option); any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include 20 | 21 | int mlua_camera__newindex(lua_State* L); 22 | int mlua_camera__index(lua_State* L); 23 | int mlua_camera_reset(lua_State*); 24 | int mlua_camera_push(lua_State *L); 25 | int mlua_camera_pop(lua_State *L); 26 | 27 | -------------------------------------------------------------------------------- /external/cjson-fpconv.patch: -------------------------------------------------------------------------------- 1 | diff --git a/fpconv.c b/fpconv.c 2 | index 7990831..c9a1330 100644 3 | --- a/fpconv.c 4 | +++ b/fpconv.c 5 | @@ -49,6 +49,7 @@ static char locale_decimal_point = '.'; 6 | * localconv() may not be thread safe (=>crash), and nl_langinfo() is 7 | * not supported on some platforms. Use sprintf() instead - if the 8 | * locale does change, at least Lua CJSON won't crash. */ 9 | +#ifndef USE_INTERNAL_FPCONV 10 | static void fpconv_update_locale() 11 | { 12 | char buf[8]; 13 | @@ -65,6 +66,13 @@ static void fpconv_update_locale() 14 | locale_decimal_point = buf[1]; 15 | } 16 | 17 | +void fpconv_init() 18 | +{ 19 | + fpconv_update_locale(); 20 | +} 21 | +#endif 22 | + 23 | + 24 | /* Check for a valid number character: [-+0-9a-yA-Y.] 25 | * Eg: -0.6e+5, infinity, 0xF0.F0pF0 26 | * 27 | @@ -196,10 +204,5 @@ int fpconv_g_fmt(char *str, double num, int precision) 28 | return len; 29 | } 30 | 31 | -void fpconv_init() 32 | -{ 33 | - fpconv_update_locale(); 34 | -} 35 | - 36 | /* vi:ai et sw=4 ts=4: 37 | */ 38 | -------------------------------------------------------------------------------- /src/event/event_bind.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #include 18 | #include 19 | 20 | #include "event.h" 21 | #include "event_bind.h" 22 | 23 | int mlua_set_relative_mode(lua_State* L) 24 | { 25 | assert(L); 26 | 27 | bool relative = lua_toboolean(L, 1); 28 | event_set_relative_mode(relative); 29 | return 0; 30 | } 31 | 32 | -------------------------------------------------------------------------------- /tests/audio/random/main.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | local sounds = { 4 | 'jump1.wav', 5 | 'jump2.wav', 6 | 'hurt1.wav', 7 | 'coin1.wav', 8 | 'coin2.wav', 9 | } 10 | 11 | local loaded = {} 12 | for i, s in pairs(sounds) do 13 | if not drystal.file_exists(s) then 14 | drystal.wget(s, s, function () 15 | local sound = drystal.load_sound(s) 16 | loaded[i] = sound 17 | end, function() print('can\'t download sound', s) end) 18 | else 19 | local sound = drystal.load_sound(s) 20 | print(sound) 21 | loaded[i] = sound 22 | end 23 | end 24 | 25 | function drystal.init() 26 | drystal.resize(400, 400) 27 | drystal.set_sound_volume(0.1) 28 | end 29 | 30 | function drystal.mouse_motion() 31 | loaded[math.random(#loaded)]:play() 32 | end 33 | 34 | function quick_play(str) 35 | local sound = drystal.load_sound(str) 36 | sound:play() 37 | end 38 | 39 | function drystal.key_press(k) 40 | if k == 't' then 41 | quick_play(sounds[math.random(#loaded)]) 42 | elseif k == 'escape' or k == 'a' then 43 | drystal.stop() 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /src/livecoding.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | int livecoding_init(void (*callback)(void *arg, const char* filename), void *arg); 20 | int livecoding_watch_directory(const char *directory); 21 | int livecoding_watch_directory_recursively(const char *path); 22 | int livecoding_quit(void); 23 | int livecoding_is_running(void); 24 | 25 | -------------------------------------------------------------------------------- /src/audio/sound_bind.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include 20 | 21 | #include "lua_util.h" 22 | #include "sound.h" 23 | 24 | DECLARE_PUSHPOP(Sound, sound) 25 | 26 | int mlua_load_sound(lua_State *L); 27 | int mlua_create_sound(lua_State *L); 28 | int mlua_play_sound(lua_State *L); 29 | int mlua_free_sound(lua_State *L); 30 | 31 | -------------------------------------------------------------------------------- /tests/event/hooks.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | function drystal.init() 4 | print'init' 5 | drystal.resize(400, 400) 6 | end 7 | 8 | function drystal.update(dt) 9 | --print('update, dt') 10 | end 11 | 12 | function drystal.draw() 13 | --print'draw' 14 | end 15 | 16 | function drystal.key_press(key) 17 | print('key_press', key) 18 | if key == 'a' then 19 | drystal.stop() 20 | end 21 | end 22 | function drystal.key_release(key) 23 | print('key_release', key) 24 | end 25 | function drystal.key_text(char) 26 | print('key_text', char) 27 | end 28 | 29 | function drystal.mouse_press(x, y, b) 30 | if b == drystal.buttons.left then 31 | print('button left pressed') 32 | end 33 | print('mouse_press', x, y, b) 34 | end 35 | function drystal.mouse_motion(x, y, dx, dy) 36 | print('mouse_motion', x, y, dx, dy) 37 | end 38 | function drystal.mouse_release(x, y, b) 39 | if b == drystal.buttons.left then 40 | print('button left released') 41 | end 42 | print('mouse_release', x, y, b) 43 | end 44 | 45 | function drystal.atexit() 46 | print'atexit' 47 | end 48 | 49 | -------------------------------------------------------------------------------- /src/web/api.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #include 18 | 19 | #include "module.h" 20 | #include "web_bind.h" 21 | #include "api.h" 22 | 23 | BEGIN_MODULE(web) 24 | #ifdef EMSCRIPTEN 25 | DECLARE_BOOLEAN(is_web, true) 26 | #else 27 | DECLARE_BOOLEAN(is_web, false) 28 | #endif 29 | DECLARE_FUNCTION(wget) 30 | DECLARE_FUNCTION(run_js) 31 | END_MODULE() 32 | 33 | -------------------------------------------------------------------------------- /tests/particle/fire.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | if not sys1 then -- for livecoding 4 | sys1 = drystal.new_system(100, 550) 5 | end 6 | 7 | sys1:set_sizes { 8 | [0]=20, 9 | [.2]={7, 10}, 10 | [1]=5, 11 | } 12 | sys1:set_colors { 13 | [0.05]=drystal.colors.red:darker(), 14 | [0.4]={'orange', 'yellow'}, 15 | [0.9]='black', 16 | } 17 | 18 | sys1:set_lifetime(3) 19 | 20 | sys1:set_direction(- math.pi / 2 - math.pi/12, -math.pi/2 + math.pi/12) 21 | sys1:set_initial_velocity(100) 22 | sys1:set_initial_acceleration(0) 23 | sys1:set_emission_rate(100) 24 | tex = drystal.load_surface('spritesheet.png') 25 | sys1:set_texture(tex, 64, 0) 26 | 27 | function drystal.init() 28 | drystal.resize(600, 600) 29 | sys1:start() 30 | end 31 | 32 | function drystal.update(dt) 33 | if dt > .06 then 34 | dt = .06 35 | end 36 | sys1:update(dt) 37 | end 38 | 39 | function drystal.draw() 40 | drystal.set_color(0, 0, 0) 41 | drystal.draw_background() 42 | 43 | sys1:draw() 44 | end 45 | 46 | function drystal.key_press(k) 47 | if k == 'a' then 48 | drystal.stop() 49 | end 50 | end 51 | 52 | -------------------------------------------------------------------------------- /tests/physics/destroy.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | drystal.init_physics(0, 0) 4 | 5 | local shape = drystal.new_shape('circle', 5) 6 | local body = drystal.new_body(true, shape) 7 | local body2 = drystal.new_body(true, shape) 8 | shape = nil 9 | collectgarbage() 10 | 11 | local joint = drystal.new_joint('distance', body, body2) 12 | 13 | print(body:get_position()) 14 | body:destroy() 15 | -- the joint should be destroyed yet 16 | 17 | if pcall(body.get_position, body) then 18 | error("body:get_position should fail after body:destroy") 19 | end 20 | if pcall(joint.destroy, joint) then 21 | error("joint:destroy should fail after body:destroy") 22 | end 23 | 24 | body = nil 25 | if pcall(joint.set_length, joint, 1) then 26 | error('joint:set_length should fail after body:destroy') 27 | end 28 | 29 | joint = nil -- no need to destroy it, body:destroy() did it 30 | collectgarbage() 31 | 32 | body2 = nil 33 | if pcall(collectgarbage) then 34 | error("body2 = nil + collectgarbage should fail because body2 hasn't been destroyed") 35 | end 36 | 37 | print 'ending' 38 | drystal.stop() 39 | 40 | -------------------------------------------------------------------------------- /src/graphics/shader_bind.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option); any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include 20 | 21 | #include "lua_util.h" 22 | #include "shader.h" 23 | 24 | DECLARE_PUSHPOP(Shader, shader) 25 | 26 | int mlua_new_shader(lua_State* L); 27 | int mlua_use_shader(lua_State* L); 28 | int mlua_use_default_shader(lua_State* L); 29 | int mlua_feed_shader(lua_State* L); 30 | int mlua_free_shader(lua_State* L); 31 | 32 | -------------------------------------------------------------------------------- /tests/font/simple_draw.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | local font, font_big 4 | function drystal.init() 5 | drystal.resize(512, 512) 6 | 7 | font = drystal.load_font('arial.ttf', 16) 8 | font_big = drystal.load_font('arial.ttf', 42) 9 | end 10 | 11 | local time = 0 12 | function drystal.update(dt) 13 | time = time + dt 14 | end 15 | 16 | local function highlight(text, pos) 17 | pos = math.floor(pos) 18 | return text:sub(0, pos-1) .. '{big|'.. text:sub(pos, pos) .. '}' .. text:sub(pos+1, -1) 19 | end 20 | 21 | function drystal.draw() 22 | drystal.set_alpha(255) 23 | drystal.set_color(200, 200, 200) 24 | drystal.draw_background() 25 | 26 | drystal.set_color(255, 0, 0) 27 | font:draw('abcdefghijklmopqrstuvwxyz', 512 / 2, 100, drystal.aligns.center) 28 | 29 | local text = 'abd {r:0|big|b:150|bla} {small|test} {big|%:50|defghi}' 30 | text = highlight(text, (math.sin(time/10)/2+0.5)*#text + 1) 31 | font_big:draw(text, 512 / 2, 512 / 2, drystal.aligns.center) 32 | 33 | font:draw_plain(text, 10, 512 * 0.7) 34 | end 35 | 36 | function drystal.key_press(k) 37 | if k == 'a' then 38 | drystal.stop() 39 | end 40 | end 41 | 42 | -------------------------------------------------------------------------------- /tests/event/relative.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | drystal.resize(800, 600) 4 | 5 | local relative = false 6 | 7 | local mx = 0 8 | local my = 0 9 | function drystal.draw() 10 | drystal.set_color(0, 0, 0) 11 | drystal.draw_background() 12 | 13 | drystal.set_color(255, 255, 255) 14 | drystal.draw_circle(mx, my, 10) 15 | end 16 | 17 | function drystal.mouse_motion(x, y, dx, dy) 18 | --print(x, y, dx, dy) 19 | if not relative then 20 | mx = x 21 | my = y 22 | else 23 | mx = mx + dx 24 | my = my + dy 25 | if mx < 0 then mx = 0 end 26 | if mx >= drystal.screen.w then mx = drystal.screen.w - 1 end 27 | if my < 0 then my = 0 end 28 | if my >= drystal.screen.h then my = drystal.screen.h - 1 end 29 | end 30 | end 31 | 32 | function drystal.key_press(k) 33 | if k == 'a' then 34 | drystal.stop() 35 | elseif k == 'space' then 36 | relative = not relative 37 | drystal.set_relative_mode(relative) 38 | print(relative) 39 | end 40 | end 41 | 42 | --drystal.run_js [[ 43 | --var canvas = document.getElementById('canvas'); 44 | --canvas.onmouseover = function() { 45 | --canvas.requestPointerLock(); 46 | --}; 47 | --]] 48 | -------------------------------------------------------------------------------- /src/font/font_bind.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include 20 | 21 | #include "lua_util.h" 22 | #include "font.h" 23 | 24 | DECLARE_PUSHPOP(Font, font) 25 | 26 | int mlua_draw_font(lua_State* L); 27 | int mlua_draw_plain_font(lua_State* L); 28 | int mlua_load_font(lua_State* L); 29 | int mlua_sizeof_font(lua_State* L); 30 | int mlua_sizeof_plain_font(lua_State* L); 31 | int mlua_free_font(lua_State* L); 32 | 33 | -------------------------------------------------------------------------------- /src/utils/api.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #include "module.h" 18 | #include "api.h" 19 | 20 | extern int json_encode(lua_State* L); 21 | extern int json_decode(lua_State* L); 22 | extern void lua_cjson_init(); 23 | 24 | BEGIN_MODULE(utils) 25 | lua_cjson_init(); 26 | 27 | lua_pushcfunction(L, json_encode); 28 | lua_setfield(L, -2, "tojson"); 29 | 30 | lua_pushcfunction(L, json_decode); 31 | lua_setfield(L, -2, "fromjson"); 32 | END_MODULE() 33 | 34 | -------------------------------------------------------------------------------- /tests/graphics/image.json: -------------------------------------------------------------------------------- 1 | {"frames": { 2 | 3 | "block.png": 4 | { 5 | "frame": {"x":2,"y":2,"w":32,"h":32}, 6 | "rotated": false, 7 | "trimmed": false, 8 | "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, 9 | "sourceSize": {"w":32,"h":32} 10 | }, 11 | "bonus.png": 12 | { 13 | "frame": {"x":36,"y":2,"w":32,"h":32}, 14 | "rotated": false, 15 | "trimmed": false, 16 | "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, 17 | "sourceSize": {"w":32,"h":32} 18 | }, 19 | "character.png": 20 | { 21 | "frame": {"x":70,"y":2,"w":32,"h":32}, 22 | "rotated": false, 23 | "trimmed": false, 24 | "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, 25 | "sourceSize": {"w":32,"h":32} 26 | }, 27 | "logo.png": 28 | { 29 | "frame": {"x":104,"y":2,"w":1023,"h":324}, 30 | "rotated": false, 31 | "trimmed": false, 32 | "spriteSourceSize": {"x":0,"y":0,"w":1023,"h":324}, 33 | "sourceSize": {"w":1023,"h":324} 34 | }}, 35 | "meta": { 36 | "app": "http://www.texturepacker.com", 37 | "version": "1.0", 38 | "image": "image.png", 39 | "format": "RGBA8888", 40 | "size": {"w":2048,"h":512}, 41 | "scale": "1", 42 | "smartupdate": "$TexturePacker:SmartUpdate:1a3d32f49cf3ed1fcd8cfad8d8f9df74$" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/graphics/sprites.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | drystal.resize(600, 400) 4 | 5 | local spritesheet = assert(drystal.fromjson(io.open('image.json'):read('*all'))) 6 | local sprite = spritesheet.frames['character.png'].frame 7 | 8 | image = assert(drystal.load_surface(spritesheet.meta.image)) 9 | image:draw_from() 10 | 11 | local sprites = {} 12 | 13 | function drystal.update(dt) 14 | for _, s in ipairs(sprites) do 15 | s:update(dt) 16 | end 17 | end 18 | 19 | function drystal.draw() 20 | drystal.set_color(20, 20, 20) 21 | drystal.draw_background() 22 | 23 | for _, s in ipairs(sprites) do 24 | s:draw() 25 | end 26 | end 27 | 28 | local s1 = drystal.new_sprite(sprite, 300, 200, 40, 40) 29 | s1.color = drystal.colors.red 30 | s1.update = function(self, dt) 31 | self.angle = self.angle + dt * math.pi * 2 32 | end 33 | 34 | local s2 = drystal.new_sprite(sprite, 150, 200, 100, 100) 35 | s2.update=function(self, dt) 36 | self.angle = self.angle + dt * math.pi * 2 37 | self.color[1] = self.color[1] + dt * 255 * 2 38 | if self.color[1] > 255 then 39 | self.color[1] = 0 40 | end 41 | end 42 | 43 | table.insert(sprites, s1) 44 | table.insert(sprites, s2) 45 | 46 | -------------------------------------------------------------------------------- /src/audio/music_bind.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include 20 | 21 | #include "music.h" 22 | #include "lua_util.h" 23 | 24 | DECLARE_PUSHPOP(Music, music) 25 | 26 | int mlua_load_music(lua_State *L); 27 | int mlua_play_music(lua_State *L); 28 | int mlua_stop_music(lua_State *L); 29 | int mlua_pause_music(lua_State *L); 30 | int mlua_free_music(lua_State *L); 31 | int mlua_set_pitch_music(lua_State *L); 32 | int mlua_set_volume_music(lua_State *L); 33 | 34 | -------------------------------------------------------------------------------- /src/event/api.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #include "module.h" 18 | #include "event_bind.h" 19 | #include "event.h" 20 | #include "api.h" 21 | 22 | BEGIN_MODULE(event) 23 | DECLARE_FUNCTION(set_relative_mode) 24 | BEGIN_ENUM() 25 | ADD_CONSTANT("left", BUTTON_LEFT) 26 | ADD_CONSTANT("middle", BUTTON_MIDDLE) 27 | ADD_CONSTANT("right", BUTTON_RIGHT) 28 | ADD_CONSTANT("wheel_up", WHEEL_UP) 29 | ADD_CONSTANT("wheel_down", WHEEL_DOWN) 30 | REGISTER_ENUM("buttons") 31 | END_MODULE() 32 | 33 | -------------------------------------------------------------------------------- /src/graphics/buffer_bind.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option); any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include 20 | 21 | #include "lua_util.h" 22 | #include "buffer.h" 23 | 24 | DECLARE_PUSHPOP(Buffer, buffer) 25 | 26 | int mlua_new_buffer(lua_State* L); 27 | int mlua_use_buffer(lua_State* L); 28 | int mlua_use_default_buffer(lua_State* L); 29 | int mlua_draw_buffer(lua_State* L); 30 | int mlua_reset_buffer(lua_State* L); 31 | int mlua_upload_and_free_buffer(lua_State* L); 32 | int mlua_free_buffer(lua_State* L); 33 | 34 | -------------------------------------------------------------------------------- /tests/font/position.lua: -------------------------------------------------------------------------------- 1 | local drystal = require "drystal" 2 | 3 | local arial 4 | function drystal.init() 5 | drystal.resize(600, 400); 6 | arial = assert(drystal.load_font('arial.ttf', 25)) 7 | end 8 | local time = 0 9 | 10 | function drystal.update(dt) 11 | time = time + dt 12 | end 13 | 14 | local shadowx = 0 15 | local shadowy = 0 16 | function drystal.draw() 17 | drystal.set_color(255, 255, 255) 18 | drystal.draw_background() 19 | 20 | drystal.set_color(0, 0, 0) 21 | local text = '{outline|outg:%f|yeah it\'s c{outg:0|o}ol!}' 22 | text = text:format((math.sin(time) / 2 + .5)*255) 23 | local y = 20 24 | local x = 20 25 | 26 | local w, h = arial:sizeof_plain(text) 27 | drystal.draw_square(x, y, w, h) 28 | arial:draw_plain(text, x, y) 29 | 30 | y = y + h + 5 31 | local w, h = arial:sizeof(text) 32 | drystal.draw_square(x, y, w, h) 33 | drystal.set_color(255, 255, 255) 34 | arial:draw(text, x, y) 35 | 36 | drystal.set_color(0, 0, 0) 37 | local shadowed = 'Oh {shadowx:%.2f|shadowy:%.2f|outline|r:200|waw!}' 38 | shadowed = shadowed:format(shadowx, shadowy) 39 | arial:draw(shadowed, 300, 200, 2) 40 | end 41 | 42 | function drystal.mouse_motion(x, y) 43 | shadowx = (300 - x) / 300 * 5 44 | shadowy = (200 - y) / 200 * 5 45 | end 46 | -------------------------------------------------------------------------------- /src/audio/sound.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include 20 | #include 21 | 22 | typedef struct Sound Sound; 23 | 24 | struct Sound { 25 | ALuint alBuffer; 26 | char* filename; 27 | bool free_me; 28 | int ref; 29 | }; 30 | 31 | void sound_play(Sound *sound, float volume, float x, float y, float pitch); 32 | void sound_free(Sound *sound); 33 | 34 | int sound_load_from_file(const char *filepath, Sound **sound); 35 | Sound *sound_load(unsigned int len, const float* buffer, int samplesrate); 36 | 37 | -------------------------------------------------------------------------------- /src/engine.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include 20 | 21 | int engine_init(const char *filename, unsigned int target_fps); 22 | void engine_free(void); 23 | void engine_load(void); 24 | void engine_loop(void); 25 | void engine_update(void); 26 | bool engine_is_loaded(void); 27 | void engine_stop(void); 28 | void engine_toggle_update(void); 29 | void engine_toggle_draw(void); 30 | #ifdef BUILD_LIVECODING 31 | void engine_wait_next_reload(void); 32 | void engine_add_file_to_reloadqueue(const char* filename); 33 | #endif 34 | 35 | -------------------------------------------------------------------------------- /src/physics/raycast.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | drystal.raw_raycast = drystal.raycast 4 | 5 | local function any(body, fraction) 6 | return 0, true 7 | end 8 | 9 | local function closest(body, fraction) 10 | return fraction, true 11 | end 12 | 13 | local function farthest(destx, desty) 14 | local distance 15 | 16 | return function(body, fraction, x, y) 17 | local d = math.distance(destx, desty, x, y) 18 | if not distance or d < distance then 19 | distance = d 20 | return 1, true 21 | end 22 | return 1, false 23 | end 24 | end 25 | 26 | local function all(bodies, points) 27 | return function(body, fraction, x, y) 28 | table.insert(bodies, body) 29 | table.insert(points, {x, y}) 30 | return 1, fraction 31 | end 32 | end 33 | 34 | function drystal.raycast(x1, y1, x2, y2, method) 35 | if method == 'any' then 36 | method = any 37 | elseif method == 'closest' then 38 | method = closest 39 | elseif method == 'farthest' or method == 'furthest' then 40 | method = farthest(x2, y2) 41 | elseif method == 'all' then 42 | local bodies = {} 43 | local points = {} 44 | drystal.raw_raycast(x1, y1, x2, y2, all(bodies, points)) 45 | return bodies, points 46 | end 47 | return drystal.raw_raycast(x1, y1, x2, y2, method) 48 | end 49 | 50 | -------------------------------------------------------------------------------- /misc/shell-completion/zsh/_drystaljs: -------------------------------------------------------------------------------- 1 | #compdef drystaljs 2 | 3 | _drystaljs_publish() { 4 | _arguments \ 5 | {-h,--help}'[Show this help message and exit]' \ 6 | {-n,--no-push}'[Do not push after commiting]' 7 | } 8 | 9 | _drystaljs_pack() { 10 | _arguments \ 11 | {-h,--help}'[Show this help message and exit]' \ 12 | {-l,--local=}'[Use a local javascript file]:javascript file:_files' 13 | } 14 | 15 | (( $+functions[_drystaljs_command] )) || _drystaljs_command() 16 | { 17 | local -a _drystaljs_cmds 18 | _drystaljs_cmds=( 19 | "init:Initialize configuration" 20 | "clean:Clean directory" 21 | "run:Run in a browser" 22 | "pack:Pack" 23 | "publish:Publish" 24 | ) 25 | if (( CURRENT == 1 )); then 26 | _describe -t commands 'drystaljs command' _drystaljs_cmds || compadd "$@" 27 | else 28 | local curcontext="$curcontext" 29 | cmd="${${_drystaljs_cmds[(r)$words[1]:*]%%:*}}" 30 | if (( $+functions[_drystaljs_$cmd] )); then 31 | _drystaljs_$cmd 32 | else 33 | _message "no more options" 34 | fi 35 | fi 36 | } 37 | 38 | _arguments \ 39 | {-h,--help}'[Show this help message and exit]' \ 40 | '*::drystaljs command:_drystaljs_command' 41 | -------------------------------------------------------------------------------- /spec/audio_spec.moon: -------------------------------------------------------------------------------- 1 | drystal = require 'drystal' 2 | 3 | describe 'audio', -> 4 | describe 'music', -> 5 | it 'loads ogg', -> 6 | with m = drystal.load_music 'tests/audio/test.ogg' 7 | assert.not_nil m 8 | 9 | it 'returns an error if the file does not exist', -> 10 | with ok, err = drystal.load_music 'does_not_exist.ogg' 11 | assert.nil ok 12 | assert.string err 13 | 14 | it 'returns an error if the file is not an ogg', -> 15 | with ok, err = drystal.load_music 'spec/surface_spec.moon' 16 | assert.nil ok 17 | assert.string err 18 | with ok, err = drystal.load_music 'tests/audio/test.wav' 19 | assert.nil ok 20 | assert.string err 21 | 22 | describe 'sound', -> 23 | it 'loads wav', -> 24 | with s = drystal.load_sound 'tests/audio/test.wav' 25 | assert.not_nil s 26 | 27 | it 'returns an error if the file does not exist', -> 28 | with ok, err = drystal.load_sound 'does_not_exist.wav' 29 | assert.nil ok 30 | assert.string err 31 | 32 | it 'returns an error if the file is not an wav', -> 33 | with ok, err = drystal.load_sound 'spec/surface_spec.moon' 34 | assert.nil ok 35 | assert.string err 36 | with ok, err = drystal.load_sound 'tests/audio/test.ogg' 37 | assert.nil ok 38 | assert.string err 39 | 40 | -------------------------------------------------------------------------------- /src/graphics/camera.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include 20 | 21 | typedef struct Camera Camera; 22 | 23 | struct Camera { 24 | float dx; 25 | float dy; 26 | float zoom; 27 | float angle; 28 | float matrix[4]; 29 | }; 30 | 31 | Camera *camera_new(void); 32 | void camera_free(Camera *c); 33 | 34 | void camera_update_matrix(Camera *c, int width, int height); 35 | void camera_reset(Camera *c); 36 | void camera_push(Camera *c); 37 | void camera_pop(Camera *c); 38 | bool camera_stack_is_full(void); 39 | bool camera_stack_is_empty(void); 40 | 41 | -------------------------------------------------------------------------------- /src/particle/particle.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include 20 | 21 | typedef struct Particle Particle; 22 | 23 | #include "system.h" 24 | 25 | struct Particle { 26 | bool dead; 27 | 28 | float x, y; 29 | float vel; 30 | float accel; 31 | float dir_angle; 32 | 33 | float life, lifetime; 34 | 35 | int size_state; 36 | float sizeseed; 37 | 38 | int color_state; 39 | float rseed; 40 | float gseed; 41 | float bseed; 42 | 43 | int alpha_state; 44 | float alphaseed; 45 | }; 46 | 47 | void particle_update(Particle *p, System *sys, float dt); 48 | 49 | -------------------------------------------------------------------------------- /src/font/api.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #include "module.h" 18 | #include "font_bind.h" 19 | #include "font.h" 20 | #include "api.h" 21 | 22 | BEGIN_MODULE(font) 23 | DECLARE_FUNCTION(load_font) 24 | 25 | BEGIN_CLASS(font) 26 | ADD_METHOD(font, draw) 27 | ADD_METHOD(font, draw_plain) 28 | ADD_METHOD(font, sizeof) 29 | ADD_METHOD(font, sizeof_plain) 30 | ADD_GC(free_font) 31 | REGISTER_CLASS(font, "Font") 32 | 33 | BEGIN_ENUM() 34 | ADD_CONSTANT("left", ALIGN_LEFT) 35 | ADD_CONSTANT("center", ALIGN_CENTER) 36 | ADD_CONSTANT("right", ALIGN_RIGHT) 37 | REGISTER_ENUM("aligns") 38 | END_MODULE() 39 | 40 | -------------------------------------------------------------------------------- /spec/color_spec.moon: -------------------------------------------------------------------------------- 1 | drystal = require 'drystal' 2 | 3 | describe 'color', -> 4 | 5 | it 'has W3C colors', -> 6 | assert.same {255, 0, 0}, {table.unpack drystal.colors.red} 7 | assert.same {0, 0, 0}, {table.unpack drystal.colors.black} 8 | 9 | it 'supports hexadecimal formatting', -> 10 | assert.same {0, 0, 0}, {table.unpack drystal.colors['#000000']} 11 | assert.same {255, 255, 255}, {table.unpack drystal.colors['#ffffff']} 12 | assert.same {15, 15, 15}, {table.unpack drystal.colors['#0f0f0f']} 13 | assert.same {16, 16, 16}, {table.unpack drystal.colors['#101010']} 14 | assert.same {255, 255, 255}, {table.unpack drystal.colors['#fff']} 15 | 16 | it 'is case insensitive', -> 17 | assert.same {table.unpack drystal.colors.Blue }, {0, 0, 255} 18 | assert.same {table.unpack drystal.colors['#0000Ff']}, {0, 0, 255} 19 | 20 | it 'throws an error if the color is unknown', -> 21 | assert.error -> drystal.colors.flava 22 | 23 | it 'can be made darker', -> 24 | c = drystal.colors.gray 25 | c2 = c\darker! 26 | assert.is_true c2.r < c.r 27 | assert.is_true c2.g < c.g 28 | assert.is_true c2.b < c.b 29 | 30 | it 'can be made lighter', -> 31 | c = drystal.colors.gray 32 | c2 = c\lighter! 33 | assert.is_true c2.r > c.r 34 | assert.is_true c2.g > c.g 35 | assert.is_true c2.b > c.b 36 | 37 | -- TODO: conversions, operators 38 | 39 | -------------------------------------------------------------------------------- /tests/particle/blood.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | local squish = assert(drystal.load_sound('squish2.wav')) 4 | tex = assert(drystal.load_surface('spritesheet.png')) 5 | local sys_blood = drystal.new_system(300, 600) 6 | 7 | sys_blood:set_sizes { 8 | [0]=50, 9 | [0.25] = 75, 10 | [0.5] = 55, 11 | [0.75] = 25, 12 | [1] = 15, 13 | } 14 | sys_blood:set_colors { 15 | [0]=drystal.colors.white, 16 | } 17 | 18 | sys_blood:set_lifetime(0.5) 19 | sys_blood:set_direction(-math.pi, math.pi) 20 | sys_blood:set_initial_velocity(50, 150) 21 | sys_blood:set_initial_acceleration(-100, 0) 22 | sys_blood:set_offset(0, 0, 0, 0) 23 | sys_blood:set_texture(tex, 128, 0) 24 | 25 | function drystal.init() 26 | drystal.resize(800, 600) 27 | end 28 | 29 | local time = 0 30 | function drystal.update(dt) 31 | time = time + dt 32 | sys_blood:update(dt) 33 | end 34 | 35 | function drystal.draw() 36 | drystal.set_color('black') 37 | drystal.draw_background() 38 | 39 | sys_blood:draw() 40 | end 41 | 42 | local last_splash = 0 43 | function drystal.mouse_press(x, y, b) 44 | if time - last_splash > 0.03 then 45 | sys_blood:emit(60) 46 | squish:play() 47 | end 48 | last_splash = time 49 | end 50 | 51 | function drystal.mouse_motion(x, y) 52 | sys_blood:set_position(x, y) 53 | end 54 | 55 | function drystal.key_press(k) 56 | if k == 'a' then 57 | drystal.stop() 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /external/zlibCMakeLists.cmake: -------------------------------------------------------------------------------- 1 | add_definitions(-DZ_HAVE_UNISTD_H -DHAVE_FSEEKO -DHAVE_SYS_TYPES_H -DHAVE_STDDEF_H -DHAVE_STDINT_H) 2 | configure_file( zlib/zconf.h.cmakein 3 | ${CMAKE_CURRENT_BINARY_DIR}/zconf.h @ONLY) 4 | include_directories(${CMAKE_CURRENT_BINARY_DIR} zlib/) 5 | 6 | set(ZLIB_PUBLIC_HDRS 7 | ${CMAKE_CURRENT_BINARY_DIR}/zconf.h 8 | zlib/zlib.h 9 | ) 10 | set(ZLIB_PRIVATE_HDRS 11 | zlib/crc32.h 12 | zlib/deflate.h 13 | zlib/gzguts.h 14 | zlib/inffast.h 15 | zlib/inffixed.h 16 | zlib/inflate.h 17 | zlib/inftrees.h 18 | zlib/trees.h 19 | zlib/zutil.h 20 | ) 21 | set(ZLIB_SRCS 22 | zlib/adler32.c 23 | zlib/compress.c 24 | zlib/crc32.c 25 | zlib/deflate.c 26 | zlib/gzclose.c 27 | zlib/gzlib.c 28 | zlib/gzread.c 29 | zlib/gzwrite.c 30 | zlib/inflate.c 31 | zlib/infback.c 32 | zlib/inftrees.c 33 | zlib/inffast.c 34 | zlib/trees.c 35 | zlib/uncompr.c 36 | zlib/zutil.c 37 | ) 38 | 39 | # parse the full version number from zlib.h and include in ZLIB_FULL_VERSION 40 | file(READ zlib/zlib.h _zlib_h_contents) 41 | string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*" 42 | "\\1" ZLIB_FULL_VERSION ${_zlib_h_contents}) 43 | 44 | add_library(zlib STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) 45 | set_target_properties(zlib PROPERTIES OUTPUT_NAME z) 46 | -------------------------------------------------------------------------------- /src/physics/shape_bind.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include "lua_util.h" 20 | 21 | struct lua_State; 22 | struct b2FixtureDef; 23 | 24 | struct Shape { 25 | b2FixtureDef* fixtureDef; 26 | int ref; 27 | }; 28 | 29 | DECLARE_PUSHPOP(Shape, shape) 30 | 31 | int mlua_new_shape(lua_State* L); 32 | int mlua_set_sensor_shape(lua_State* L); 33 | int mlua_gc_shape(lua_State* L); 34 | 35 | #define __SHAPE_GET_SET(value) \ 36 | int mlua_set_##value##_shape(lua_State* L); \ 37 | int mlua_get_##value##_shape(lua_State* L); 38 | 39 | __SHAPE_GET_SET(density) 40 | __SHAPE_GET_SET(restitution) 41 | __SHAPE_GET_SET(friction) 42 | 43 | #undef __SHAPE_GET_SET 44 | 45 | -------------------------------------------------------------------------------- /src/physics/world_bind.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | struct lua_State; 20 | 21 | extern float pixels_per_meter; 22 | 23 | int mlua_init_physics(lua_State* L); 24 | int mlua_set_gravity(lua_State* L); 25 | int mlua_get_gravity(lua_State* L); 26 | int mlua_set_pixels_per_meter(lua_State* L); 27 | int mlua_get_pixels_per_meter(lua_State* L); 28 | int mlua_update_physics(lua_State* L); 29 | int mlua_on_collision(lua_State* L); 30 | int mlua_raycast(lua_State* L); 31 | int mlua_query(lua_State* L); 32 | int mlua_new_body(lua_State* L); 33 | int mlua_destroy_body(lua_State* L); 34 | int mlua_new_joint(lua_State* L); 35 | int mlua_destroy_joint(lua_State* L); 36 | 37 | -------------------------------------------------------------------------------- /src/graphics/opengl_util.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #ifndef EMSCRIPTEN 20 | #include 21 | #include 22 | #else 23 | #include 24 | #include 25 | #endif 26 | 27 | #include 28 | 29 | #include "log.h" 30 | 31 | void check_opengl_oom(void); 32 | 33 | #ifndef NDEBUG 34 | const char* getGLError(GLenum error); 35 | 36 | #define GLDEBUG(x) \ 37 | x; \ 38 | { \ 39 | GLenum e; \ 40 | while((e = glGetError()) != GL_NO_ERROR) \ 41 | { \ 42 | log_debug("%s for call %s", getGLError(e), #x); \ 43 | exit(1); \ 44 | } \ 45 | } 46 | #else 47 | #define GLDEBUG(x) \ 48 | x; 49 | #endif 50 | 51 | -------------------------------------------------------------------------------- /tests/audio/create.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | local w = 800 4 | local h = 500 5 | local x = w/2 6 | local y = h/2 7 | local RATE = 44100 8 | 9 | local current = 0 10 | 11 | function play(time, ...) 12 | local freqs = {...} 13 | print("gen...") 14 | local new = drystal.load_sound(function(i) 15 | local s = 0 16 | for _, f in ipairs(freqs) do 17 | s = s + math.sin(i*f*math.pi / RATE) 18 | end 19 | s = s / #freqs 20 | return s 21 | end, time*RATE) 22 | new:play(0.15) 23 | print("play at", ...) 24 | end 25 | 26 | local cursor = 0 27 | function music_callback(data, len) 28 | local freq = 1800 * x / w 29 | local tone = freq * math.pi / RATE 30 | for i = 1, len do 31 | data[i] = math.sin(cursor * tone) 32 | cursor = cursor + 1 33 | end 34 | return len 35 | end 36 | 37 | local music 38 | function drystal.init() 39 | drystal.resize(w, h) 40 | drystal.set_music_volume(.2) 41 | music = drystal.load_music(music_callback, RATE) 42 | music:play() 43 | end 44 | 45 | function drystal.mouse_motion(xx, yy) 46 | x = xx 47 | y = yy 48 | music:set_pitch(3.5 * y / h + 0.5) 49 | end 50 | 51 | function drystal.key_press(k) 52 | if k == 'p' then 53 | music:stop() 54 | elseif k == 'o' then 55 | music:play() 56 | elseif k == 'a' then 57 | drystal.stop() 58 | elseif k == 's' then 59 | local f = {} 60 | for i = 1, 10 do 61 | f[i] = 1000 + i * 10.52 62 | end 63 | play(1, unpack(f)) 64 | end 65 | end 66 | 67 | -------------------------------------------------------------------------------- /src/audio/api.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #include "module.h" 18 | #include "audio_bind.h" 19 | #include "music_bind.h" 20 | #include "sound_bind.h" 21 | #include "api.h" 22 | 23 | BEGIN_MODULE(audio) 24 | DECLARE_FUNCTION(load_music) 25 | DECLARE_FUNCTION(set_music_volume) 26 | 27 | DECLARE_FUNCTION(load_sound) 28 | DECLARE_FUNCTION(set_sound_volume) 29 | 30 | BEGIN_CLASS(sound) 31 | ADD_METHOD(sound, play) 32 | ADD_GC(free_sound) 33 | REGISTER_CLASS(sound, "Sound") 34 | 35 | BEGIN_CLASS(music) 36 | ADD_METHOD(music, play) 37 | ADD_METHOD(music, stop) 38 | ADD_METHOD(music, pause) 39 | ADD_METHOD(music, set_pitch) 40 | ADD_METHOD(music, set_volume) 41 | ADD_GC(free_music) 42 | REGISTER_CLASS(music, "Music") 43 | END_MODULE() 44 | 45 | -------------------------------------------------------------------------------- /src/event/event.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include 20 | 21 | #ifndef EMSCRIPTEN 22 | #include 23 | #else 24 | #include 25 | #endif 26 | 27 | enum Button { 28 | BUTTON_LEFT = SDL_BUTTON_LEFT, 29 | BUTTON_MIDDLE = SDL_BUTTON_MIDDLE, 30 | BUTTON_RIGHT = SDL_BUTTON_RIGHT, 31 | BUTTON_EXTRA_LEFT = SDL_BUTTON_X1, 32 | BUTTON_EXTRA_RIGHT = SDL_BUTTON_X2, 33 | // There is no more WHEEL_UP constant in SDL2 so we create ours 34 | WHEEL_UP = 4, 35 | WHEEL_DOWN = 5, 36 | }; 37 | typedef enum Button Button; 38 | 39 | void event_update(void); 40 | void event_small_update(void); 41 | void event_destroy(void); 42 | int event_init(void); 43 | 44 | void event_set_relative_mode(bool relative); 45 | 46 | -------------------------------------------------------------------------------- /src/audio/audio_bind.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #include 18 | #include 19 | #include 20 | 21 | #include "audio_bind.h" 22 | #include "lua_util.h" 23 | #include "audio.h" 24 | 25 | int mlua_set_sound_volume(lua_State *L) 26 | { 27 | assert(L); 28 | 29 | float volume = luaL_checknumber(L, 1); 30 | 31 | assert_lua_error(L, volume >= 0 && volume <= 1, "set_sound_volume: must be >= 0 and <= 1"); 32 | 33 | audio_set_sound_volume(volume); 34 | return 0; 35 | } 36 | 37 | int mlua_set_music_volume(lua_State *L) 38 | { 39 | assert(L); 40 | 41 | float volume = luaL_checknumber(L, 1); 42 | 43 | assert_lua_error(L, volume >= 0 && volume <= 1, "set_music_volume: must be >= 0 and <= 1"); 44 | 45 | audio_set_music_volume(volume); 46 | return 0; 47 | } 48 | 49 | -------------------------------------------------------------------------------- /src/dlua.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #include 24 | #include 25 | 26 | void dlua_init(const char *filename); 27 | void dlua_add_arg(const char*); 28 | 29 | lua_State *dlua_get_lua_state(void); 30 | 31 | bool dlua_load_code(void); 32 | bool dlua_reload_code(void); 33 | 34 | void dlua_call_init(void); 35 | void dlua_call_update(float dt); 36 | void dlua_call_draw(void); 37 | void dlua_call_atexit(void); 38 | bool dlua_foreach(const char* type, bool(*callback)(void* data, const void* callback_arg), const void* callback_arg); 39 | 40 | void dlua_get_drystal_field(const char* name); 41 | bool dlua_get_function(const char* name); 42 | void dlua_free(void); 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | 48 | -------------------------------------------------------------------------------- /src/particle/particle.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #include "particle.h" 22 | #include "system.h" 23 | 24 | void particle_update(Particle *p, System *s, float dt) 25 | { 26 | assert(p); 27 | assert(s); 28 | 29 | p->life -= dt; 30 | 31 | p->vel += p->accel * dt; 32 | p->x += p->vel * cosf(p->dir_angle) * dt; 33 | p->y += p->vel * sinf(p->dir_angle) * dt; 34 | 35 | float liferatio = 1 - p->life / p->lifetime; 36 | if (liferatio > s->sizes[p->size_state + 1].at && p->size_state < s->cur_size) { 37 | p->size_state += 1; 38 | } 39 | if (liferatio > s->colors[p->color_state + 1].at && p->color_state < s->cur_color) { 40 | p->color_state += 1; 41 | } 42 | if (liferatio > s->alphas[p->alpha_state + 1].at && p->alpha_state < s->cur_alpha) { 43 | p->alpha_state += 1; 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /src/graphics/opengl_util.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #ifndef EMSCRIPTEN 18 | #include 19 | #include 20 | #else 21 | #include 22 | #include 23 | #endif 24 | 25 | #include "opengl_util.h" 26 | #include "log.h" 27 | 28 | void check_opengl_oom(void) 29 | { 30 | GLenum e; 31 | 32 | e = glGetError(); 33 | if (e == GL_OUT_OF_MEMORY) 34 | log_oom_and_exit(); 35 | } 36 | 37 | #ifndef NDEBUG 38 | const char* getGLError(GLenum error) 39 | { 40 | #define casereturn(x) case x: return #x 41 | switch (error) { 42 | casereturn(GL_INVALID_ENUM); 43 | casereturn(GL_INVALID_VALUE); 44 | casereturn(GL_INVALID_OPERATION); 45 | casereturn(GL_INVALID_FRAMEBUFFER_OPERATION); 46 | casereturn(GL_OUT_OF_MEMORY); 47 | default: 48 | case GL_NO_ERROR: 49 | return ""; 50 | } 51 | #undef casereturn 52 | } 53 | #endif 54 | 55 | -------------------------------------------------------------------------------- /tests/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Emscripten-Generated Code 7 | 15 | 16 | 17 | 18 | 19 | 20 | 36 | {{{DRYSTAL_ADD_ARGUMENTS}}} 37 | {{{DRYSTAL_LOAD}}} 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/web/web_bind.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #include 18 | #include 19 | #include 20 | #ifdef EMSCRIPTEN 21 | #include 22 | #endif 23 | 24 | #include "web.h" 25 | #include "web_bind.h" 26 | #include "log.h" 27 | 28 | int mlua_run_js(lua_State* L) 29 | { 30 | assert(L); 31 | 32 | #ifdef EMSCRIPTEN 33 | const char* script = luaL_checkstring(L, 1); 34 | char *ret = run_js(script); 35 | lua_pushstring(L, ret); 36 | free(ret); 37 | return 1; 38 | #else 39 | return luaL_error(L, "run_js isn't available in native build"); 40 | #endif 41 | } 42 | 43 | int mlua_wget(lua_State *L) 44 | { 45 | assert(L); 46 | 47 | #ifdef EMSCRIPTEN 48 | const char *url = luaL_checkstring(L, 1); 49 | const char *filename = luaL_checkstring(L, 2); 50 | wget(url, filename); 51 | return 0; 52 | #else 53 | return luaL_error(L, "wget isn't available in native build"); 54 | #endif 55 | } 56 | 57 | -------------------------------------------------------------------------------- /tests/graphics/filter.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | local spritesheet = assert(drystal.fromjson(io.open('image.json'):read('*all'))) 4 | local image = assert(drystal.load_surface(spritesheet.meta.image)) 5 | 6 | drystal.resize(600, 400) 7 | image:draw_from() 8 | 9 | local spritesrc = spritesheet.frames['character.png'].frame 10 | local sprite = drystal.new_sprite(spritesrc, 300, 180) 11 | sprite.angle = math.pi/3 12 | local sprite2 = drystal.new_sprite(spritesrc, 220, 180, spritesrc.w*2, spritesrc.h*2) 13 | sprite2.angle = math.pi/2 14 | local sprite3 = drystal.new_sprite(spritesrc, 350, 180, spritesrc.w*2, spritesrc.h*2) 15 | sprite3.angle = math.pi/2 16 | 17 | function drystal.draw() 18 | drystal.draw_background() 19 | 20 | sprite:draw() 21 | sprite2:draw() 22 | sprite3:draw() 23 | local t = { 24 | angle=0, 25 | wfactor=1, 26 | hfactor=1, 27 | } 28 | drystal.draw_sprite({x=spritesrc.x, y=spritesrc.y, w=spritesrc.w, h=spritesrc.h}, 300, 220, t) 29 | end 30 | 31 | function drystal.key_press(k) 32 | if k == '[1]' then 33 | image:set_filter(drystal.filters.nearest) 34 | elseif k == '[2]' then 35 | image:set_filter(drystal.filters.linear) 36 | elseif k == '[3]' then 37 | image:set_filter(drystal.filters.bilinear) 38 | elseif k == '[4]' then 39 | image:set_filter(drystal.filters.trilinear) 40 | elseif k == 'a' then 41 | drystal.stop() 42 | end 43 | end 44 | 45 | function drystal.mouse_press(x, y, b) 46 | if b == drystal.WHEEL_UP then 47 | drystal.camera.zoom = drystal.camera.zoom * 1.2 48 | elseif b == drystal.WHEEL_DOWN then 49 | drystal.camera.zoom = drystal.camera.zoom / 1.2 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /spec/tools.moon: -------------------------------------------------------------------------------- 1 | drystal = require 'drystal' 2 | 3 | say = require 'say' 4 | assert = require 'luassert' 5 | util = require 'luassert.util' 6 | 7 | fmt_color = (arg) -> 8 | if type(arg) == 'table' and arg.color 9 | if arg.name 10 | if arg[4] 11 | ('{%q, %d}')\format(arg.name, arg[4]) 12 | else 13 | ('%q')\format(arg.name) 14 | elseif #arg == 3 15 | ('{%d, %d, %d}')\format table.unpack arg 16 | elseif #arg == 4 17 | ('{%d, %d, %d, %d}')\format table.unpack arg 18 | 19 | is_color = (state, args) -> 20 | surface, x, y, color, alpha = table.unpack args 21 | alpha = alpha or 255 22 | 23 | assert(#args >= 4, say("assertion.internal.argtolittle", { "is_color", 4, #args })) 24 | assert(type(surface) == 'userdata' and surface.__type == 'surface', say("assertion.internal.badargtype", { 1, "is_color", "surface", surface or 'nil' })) 25 | 26 | c = color 27 | if type(color) ~= 'table' 28 | c = { table.unpack drystal.colors[color] } 29 | c.name = color 30 | else 31 | c = { table.unpack c } 32 | c[4] = alpha 33 | c.color = true 34 | 35 | old_on = drystal.current_draw_on == surface 36 | other = surface == drystal.screen and drystal.new_surface(x, y) or drystal.screen 37 | other\draw_on! if old_on 38 | r, g, b, a = surface\get_pixel x, y 39 | surface\draw_on! if old_on 40 | 41 | args[1] = c 42 | args[2] = {r, g, b, a, color: true} 43 | 44 | r == c[1] and g == c[2] and b == c[3] and a == alpha 45 | 46 | say\set_namespace "en" 47 | say\set "assertion.color.positive", "Expected surface to be %s, was %s" 48 | 49 | assert\register "assertion", "color", is_color, "assertion.color.positive" 50 | assert\add_formatter fmt_color 51 | 52 | -------------------------------------------------------------------------------- /src/font/parser.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include 20 | #include 21 | 22 | typedef struct TextState TextState; 23 | 24 | struct TextState { 25 | float size; 26 | float italic; 27 | 28 | int r; 29 | int g; 30 | int b; 31 | int alpha; 32 | 33 | bool outlined; 34 | bool shadow; 35 | 36 | int outr; 37 | int outg; 38 | int outb; 39 | 40 | float shadow_x; 41 | float shadow_y; 42 | }; 43 | 44 | static inline void textstate_reset(TextState *t) 45 | { 46 | assert(t); 47 | 48 | t->size = 1.0; 49 | t->italic = 0.0; 50 | t->r = 0; 51 | t->g = 0; 52 | t->b = 0; 53 | t->alpha = 255; 54 | t->outlined = false; 55 | t->outr = 0; 56 | t->outg = 0; 57 | t->outb = 0; 58 | t->shadow = false; 59 | t->shadow_x = 0; 60 | t->shadow_y = 0; 61 | } 62 | 63 | TextState* push_parser(void); 64 | bool parse(TextState **state, const char **text, const char **end); 65 | void pop_parser(void); 66 | 67 | -------------------------------------------------------------------------------- /src/font/font.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include 20 | 21 | typedef struct Font Font; 22 | 23 | #include "graphics/surface.h" 24 | 25 | enum Alignment { 26 | ALIGN_LEFT = 1, 27 | ALIGN_CENTER = 2, 28 | ALIGN_RIGHT = 3 29 | }; 30 | typedef enum Alignment Alignment; 31 | 32 | struct Font { 33 | Surface* surface; 34 | float font_size; 35 | int first_char; 36 | int num_chars; 37 | int ref; 38 | stbtt_bakedchar* char_data; 39 | }; 40 | 41 | void font_free(Font *font); 42 | void font_draw(const Font *f, const char* text, float x, float y, Alignment align); 43 | void font_draw_plain(const Font *f, const char* text, float x, float y); 44 | void font_get_textsize(const Font *f, const char* text, float* w, float* h, int nblines); 45 | void font_get_textsize_plain(const Font *f, const char* text, float* w, float* h); 46 | 47 | Font* font_load(const char* filename, float size, int first_char, int num_chars); 48 | 49 | -------------------------------------------------------------------------------- /tests/graphics/fx.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | drystal.resize(800, 600) 4 | 5 | local gray = false 6 | local multiply = false 7 | local distortion = false 8 | local blur = false 9 | local vignette = false 10 | local pixelate = false 11 | 12 | local time = 0 13 | function drystal.update(dt) 14 | time = time + dt 15 | end 16 | 17 | function drystal.draw(dt) 18 | drystal.set_alpha(255) 19 | drystal.set_color(255, 255, 255) 20 | drystal.draw_background() 21 | 22 | drystal.set_color(255, 0, 0) 23 | drystal.draw_rect(50, 50, 300, 200) 24 | 25 | drystal.set_color(0, 0, 100) 26 | drystal.set_alpha(200) 27 | drystal.draw_rect(10, 10, 100, 100) 28 | 29 | drystal.set_color(0, 255, 100) 30 | drystal.set_alpha(255) 31 | drystal.draw_rect(100, 100, 100, 100) 32 | 33 | if vignette then 34 | drystal.postfx('vignette', .7, (math.sin(time)/2 + 0.5) * .2 + .2) 35 | end 36 | if multiply then 37 | drystal.postfx('multiply', 1.9, .8, .7) 38 | end 39 | if gray then 40 | drystal.postfx('gray', math.sin(time)/2 + .5) 41 | end 42 | if distortion then 43 | drystal.postfx('distortion', time, 20, 0) 44 | end 45 | if pixelate then 46 | local s = (math.sin(time / 10) / 2 + .5) * 16 47 | drystal.postfx('pixelate', s, s) 48 | end 49 | if blur then 50 | drystal.postfx('blur', 90) 51 | end 52 | end 53 | 54 | function drystal.key_press(k) 55 | if k == 'a' then 56 | drystal.stop() 57 | elseif k == 'g' then 58 | gray = not gray 59 | elseif k == 'm' then 60 | multiply = not multiply 61 | elseif k == 'd' then 62 | distortion = not distortion 63 | elseif k == 'b' then 64 | blur = not blur 65 | elseif k == 'v' then 66 | vignette = not vignette 67 | elseif k == 'p' then 68 | pixelate = not pixelate 69 | end 70 | end 71 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | NATIVE_CMAKE_BUILD_TYPE ?= Debug 2 | WEB_CMAKE_BUILD_TYPE ?= Release 3 | BUILD_DIRS = $(dir $(wildcard ./build-*/)) 4 | SUBDIRSCLEAN = $(addsuffix .clean,$(BUILD_DIRS)) 5 | EMSCRIPTEN = /usr/lib/emscripten/ 6 | 7 | CMAKE_FLAGS ?= 8 | 9 | # from the Makefile of neovim 10 | BUILD_TYPE ?= $(shell (type ninja > /dev/null 2>&1 && echo "Ninja") || \ 11 | echo "Unix Makefiles") 12 | ifeq (,$(BUILD_TOOL)) 13 | ifeq (Ninja,$(BUILD_TYPE)) 14 | ifneq ($(shell cmake --help 2>/dev/null | grep Ninja),) 15 | BUILD_TOOL := ninja 16 | else 17 | # User's version of CMake doesn't support Ninja 18 | BUILD_TOOL = $(MAKE) 19 | BUILD_TYPE := Unix Makefiles 20 | endif 21 | else 22 | BUILD_TOOL = $(MAKE) 23 | endif 24 | endif 25 | 26 | all: native 27 | 28 | native: 29 | mkdir -p build-native-$(NATIVE_CMAKE_BUILD_TYPE) 30 | cd build-native-$(NATIVE_CMAKE_BUILD_TYPE) && cmake .. -G '$(BUILD_TYPE)' -DCMAKE_BUILD_TYPE=$(NATIVE_CMAKE_BUILD_TYPE) $(CMAKE_FLAGS) 31 | +$(BUILD_TOOL) -C build-native-$(NATIVE_CMAKE_BUILD_TYPE) 32 | 33 | install-native: native 34 | +$(BUILD_TOOL) -C build-native-$(NATIVE_CMAKE_BUILD_TYPE) install 35 | 36 | install: install-native 37 | 38 | web: 39 | mkdir -p build-web-$(WEB_CMAKE_BUILD_TYPE) 40 | cd build-web-$(WEB_CMAKE_BUILD_TYPE) && cmake .. -G '$(BUILD_TYPE)' -DCMAKE_BUILD_TYPE=$(WEB_CMAKE_BUILD_TYPE) -DCMAKE_TOOLCHAIN_FILE=$(EMSCRIPTEN)/cmake/Modules/Platform/Emscripten.cmake $(CMAKE_FLAGS) 41 | +$(BUILD_TOOL) -C build-web-$(WEB_CMAKE_BUILD_TYPE) 42 | 43 | clean: $(SUBDIRSCLEAN) 44 | 45 | $(SUBDIRSCLEAN): 46 | $(BUILD_TOOL) -C $(basename $@) clean || true 47 | 48 | distclean: clean 49 | rm -rf $(BUILD_DIRS) 50 | 51 | .PHONY: clean distclean $(SUBDIRSCLEAN) install native web install-native 52 | -------------------------------------------------------------------------------- /tests/graphics/shaders.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | local shader 4 | 5 | local vert = [[ 6 | #ifdef GL_ES 7 | precision highp float; 8 | #endif 9 | 10 | attribute vec2 position; 11 | attribute vec4 color; 12 | attribute vec2 texCoord; 13 | attribute float pointSize; 14 | 15 | varying vec4 fColor; 16 | varying vec2 fTexCoord; 17 | 18 | uniform vec2 destinationSize; 19 | uniform vec2 sourceSize; 20 | 21 | uniform float mx; 22 | uniform float my; 23 | 24 | void main() 25 | { 26 | gl_PointSize = pointSize; 27 | vec2 pos = 2. * position / destinationSize - 1.; 28 | gl_Position = vec4(pos, mx*my+pos.x*pos.y, 1.0); 29 | vec3 offcolor = vec3(pos, pos.x + pos.y) - vec3(mx, my, mx*my); 30 | fColor = color - vec4(offcolor, 0.); 31 | fTexCoord = texCoord / sourceSize; 32 | } 33 | ]] 34 | local fragcolor = [[ 35 | ]] 36 | local fragtex = [[ 37 | ]] 38 | 39 | local mx, my 40 | local width = 1024 41 | local height = 768 42 | 43 | function drystal.init() 44 | drystal.resize(width, height) 45 | shader = assert(drystal.new_shader(vert, fragcolor, fragtex)) 46 | end 47 | 48 | function drystal.draw() 49 | drystal.set_alpha(255) 50 | drystal.set_color(0, 0, 0) 51 | drystal.draw_background() 52 | 53 | shader:use() 54 | drystal.set_color(255, 255, 255) 55 | drystal.draw_rect(0, 0, width, height) 56 | for ii = 0, 5 do 57 | local i = ii / 10 58 | drystal.draw_rect(width*i, height*i, width*(1-i*2), height*(1-i*2)) 59 | end 60 | 61 | drystal.use_default_shader() 62 | end 63 | 64 | function drystal.key_press(key) 65 | if key == 'a' then 66 | drystal.stop() 67 | end 68 | end 69 | 70 | function drystal.mouse_motion(x, y) 71 | mx, my = x, y 72 | shader:feed('mx', (mx/width) * 2 - 1) 73 | shader:feed('my', (1-my/height) * 2 - 1) 74 | end 75 | 76 | -------------------------------------------------------------------------------- /src/web/web.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #ifdef EMSCRIPTEN 18 | #include 19 | #include 20 | #include 21 | 22 | #include "web.h" 23 | #include "dlua.h" 24 | #include "lua_util.h" 25 | #include "util.h" 26 | 27 | char *run_js(const char* script) 28 | { 29 | char *ret = emscripten_run_script_string(script); 30 | return xstrdup(ret); 31 | } 32 | 33 | static void onsuccess(const char* filename) 34 | { 35 | assert(filename); 36 | 37 | if (dlua_get_function("on_wget_success")) { 38 | lua_State* L = dlua_get_lua_state(); 39 | lua_pushstring(L, filename); 40 | call_lua_function(L, 1, 0); 41 | } 42 | } 43 | 44 | static void onerror(const char* filename) 45 | { 46 | assert(filename); 47 | 48 | if (dlua_get_function("on_wget_error")) { 49 | lua_State* L = dlua_get_lua_state(); 50 | lua_pushstring(L, filename); 51 | call_lua_function(L, 1, 0); 52 | } 53 | } 54 | 55 | void wget(const char* url, const char* filename) 56 | { 57 | emscripten_async_wget(url, filename, onsuccess, onerror); 58 | } 59 | #endif 60 | 61 | -------------------------------------------------------------------------------- /cmake/BuildCoverage.cmake: -------------------------------------------------------------------------------- 1 | if(BUILD_ENABLE_COVERAGE) 2 | find_program(COVERAGE_GCOV gcov) 3 | find_program(COVERAGE_LCOV lcov) 4 | find_program(COVERAGE_GENHTML genhtml) 5 | if (NOT COVERAGE_GCOV) 6 | message(FATAL_ERROR "Unable to find gcov") 7 | endif() 8 | if (NOT COVERAGE_LCOV) 9 | message(FATAL_ERROR "Unable to find lcov") 10 | endif() 11 | if (NOT COVERAGE_GENHTML) 12 | message(FATAL_ERROR "Unable to find genhtml") 13 | endif() 14 | 15 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fprofile-arcs -ftest-coverage") 16 | set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fprofile-arcs -ftest-coverage") 17 | set(CMAKE_LD_FLAGS_DEBUG "${CMAKE_LD_FLAGS_DEBUG} -fprofile-arcs -ftest-coverage") 18 | 19 | add_custom_target(coverage-reset DEPENDS ${DRYSTAL_OUT}) 20 | add_custom_command(TARGET coverage-reset 21 | COMMAND mkdir -p coverage 22 | COMMAND ${COVERAGE_LCOV} --directory . --zerocounters 23 | WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" 24 | ) 25 | add_custom_target(coverage-report DEPENDS ${DRYSTAL_OUT}) 26 | add_custom_command(TARGET coverage-report 27 | COMMAND ${COVERAGE_LCOV} --directory . --capture --output-file ./coverage/drystal.lcov 28 | COMMAND ${COVERAGE_LCOV} --remove ./coverage/drystal.lcov --output-file ./coverage/drystal_clean.lcov '/usr/*' 'box2d/*' 29 | COMMAND ${COVERAGE_GENHTML} -t "drystal coverage" -p "${CMAKE_SOURCE_DIR}" -o ./coverage ./coverage/drystal_clean.lcov 30 | COMMAND echo "Open ${CMAKE_BINARY_DIR}/coverage/index.html to view the coverage analysis results." 31 | WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" 32 | ) 33 | target_link_libraries(${DRYSTAL_OUT} gcov) 34 | endif(BUILD_ENABLE_COVERAGE) 35 | 36 | -------------------------------------------------------------------------------- /spec/camera_spec.moon: -------------------------------------------------------------------------------- 1 | drystal = require 'drystal' 2 | 3 | describe 'camera', -> 4 | camera = drystal.camera 5 | screen = drystal.screen 6 | 7 | before_each -> 8 | pcall -> 9 | while true 10 | camera.pop! 11 | camera.reset! 12 | 13 | it 'initializes the fields', -> 14 | assert.equals 0, camera.x 15 | assert.equals 0, camera.y 16 | assert.equals 0, camera.angle 17 | assert.equals 1, camera.zoom 18 | 19 | it 'resets properly', -> 20 | camera.x = 10 21 | assert.not_equals 0, camera.x 22 | camera.reset! 23 | assert.equals 0, camera.x 24 | 25 | it 'can move', -> 26 | camera.x = 10 27 | camera.y = 15 28 | assert.equals 10, camera.x 29 | assert.equals 15, camera.y 30 | 31 | it 'can rotate', -> 32 | a = math.pi 33 | camera.angle = a 34 | assert.equals a, camera.angle 35 | 36 | it 'can zoom', -> 37 | z = 1.1 38 | camera.zoom = z 39 | assert.equals z, camera.zoom 40 | 41 | it 'throws an error when the stack is empty', -> 42 | assert.error -> camera.pop! 43 | 44 | it 'throws an error when the stack is full', -> 45 | assert.error -> 46 | while true 47 | camera.push! 48 | 49 | it 'copies values when pushing', -> 50 | camera.x = 10 51 | assert.equals 10, camera.x 52 | camera.push! 53 | assert.equals 10, camera.x 54 | 55 | it 'restores values when popping', -> 56 | camera.x = 5 57 | camera.push! 58 | camera.x = 10 59 | camera.pop! 60 | assert.equals 5, camera.x 61 | 62 | describe 'screen2scene', -> 63 | 64 | it 'is correct when simple', -> 65 | x, y = drystal.screen2scene 0, 0 66 | assert.equals 0, x 67 | assert.equals 0, y 68 | 69 | x, y = drystal.screen2scene screen.w, screen.h 70 | assert.equals screen.w, x 71 | assert.equals screen.h, y 72 | 73 | -- TODO: moved, rotated, zoomed 74 | 75 | -------------------------------------------------------------------------------- /tests/audio/play.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | local piou = assert(drystal.load_sound("test.wav")) 4 | 5 | function drystal.init() 6 | print("press p to play a wav sound") 7 | print("press i to play a ogg music") 8 | print("press o to pause a ogg music") 9 | print("press u to stop a ogg music") 10 | print("press b to toggle looping") 11 | print("press l to lower the volume of every music") 12 | print("press z to lower the volume of every sound") 13 | print("press t to set the music volume to 0.5") 14 | print("press - to decrease the pitch") 15 | print("press + to increase the pitch") 16 | drystal.resize(40, 40) 17 | end 18 | 19 | local music = assert(drystal.load_music("test.ogg")) 20 | 21 | local pitch = 1.0 22 | local sound_volume = 1.0 23 | local music_volume = 1.0 24 | local loop = false 25 | function drystal.key_press(key) 26 | if key == 'a' then 27 | drystal.stop() 28 | elseif key == 'p' then 29 | piou:play(1, 0, 0, pitch) 30 | print('play sound') 31 | elseif key == '[+]' then 32 | pitch = pitch + 0.10 33 | music:set_pitch(pitch) 34 | print('pitch: ', pitch) 35 | elseif key == '[-]' then 36 | pitch = pitch - 0.10 37 | music:set_pitch(pitch) 38 | print('pitch: ', pitch) 39 | elseif key == 't' then 40 | music:set_volume(0.5) 41 | elseif key == 'l' then 42 | music_volume = music_volume - 0.3 43 | drystal.set_music_volume(music_volume) 44 | elseif key == 'z' then 45 | sound_volume = sound_volume - 0.3 46 | drystal.set_sound_volume(sound_volume) 47 | elseif key == 'i' then 48 | music:play(loop, function() 49 | print "music ended" 50 | end) 51 | print('play music') 52 | elseif key == 'o' then 53 | music:pause() 54 | print('pause music') 55 | elseif key == 'u' then 56 | music:stop() 57 | print('stop music') 58 | elseif key == 'b' then 59 | loop = not loop 60 | print('loop:', loop) 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /src/graphics/display_bind.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option); any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include 20 | 21 | #include "lua_util.h" 22 | #include "surface.h" 23 | 24 | DECLARE_PUSHPOP(Surface, surface) 25 | 26 | int mlua_set_color(lua_State* L); 27 | int mlua_set_alpha(lua_State* L); 28 | int mlua_set_title(lua_State* L); 29 | int mlua_set_blend_mode(lua_State* L); 30 | 31 | int mlua_show_cursor(lua_State* L); 32 | int mlua_resize(lua_State* L); 33 | int mlua_set_fullscreen(lua_State* L); 34 | int mlua_screen2scene(lua_State* L); 35 | 36 | int mlua_surface_class_index(lua_State* L); 37 | int mlua_load_surface(lua_State* L); 38 | int mlua_new_surface(lua_State* L); 39 | int mlua_free_surface(lua_State* L); 40 | int mlua_draw_on_surface(lua_State* L); 41 | int mlua_draw_from_surface(lua_State* L); 42 | int mlua_set_filter_surface(lua_State* L); 43 | int mlua_get_pixel_surface(lua_State* L); 44 | 45 | int mlua_draw_background(lua_State *L); 46 | int mlua_draw_point(lua_State* L); 47 | int mlua_draw_point_tex(lua_State* L); 48 | int mlua_draw_line(lua_State* L); 49 | int mlua_draw_triangle(lua_State* L); 50 | int mlua_draw_surface(lua_State* L); 51 | int mlua_draw_quad(lua_State* L); 52 | 53 | -------------------------------------------------------------------------------- /src/particle/api.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #include "module.h" 18 | #include "system_bind.h" 19 | #include "api.h" 20 | 21 | BEGIN_MODULE(particle) 22 | DECLARE_FUNCTION(new_system) 23 | 24 | BEGIN_CLASS(system) 25 | ADD_METHOD(system, emit) 26 | ADD_METHOD(system, start) 27 | ADD_METHOD(system, stop) 28 | ADD_METHOD(system, reset) 29 | 30 | ADD_METHOD(system, draw) 31 | ADD_METHOD(system, update) 32 | ADD_METHOD(system, add_size) 33 | ADD_METHOD(system, add_color) 34 | ADD_METHOD(system, add_alpha) 35 | ADD_METHOD(system, clear_sizes) 36 | ADD_METHOD(system, clear_colors) 37 | ADD_METHOD(system, clear_alphas) 38 | ADD_METHOD(system, set_texture) 39 | 40 | ADD_GETSET(system, position) 41 | ADD_GETSET(system, offset) 42 | ADD_GETSET(system, emission_rate) 43 | 44 | #define ADD_MINMAX(name) \ 45 | ADD_GETSET(system, min_##name) \ 46 | ADD_GETSET(system, max_##name) 47 | ADD_MINMAX(lifetime) 48 | ADD_MINMAX(direction) 49 | ADD_MINMAX(initial_acceleration) 50 | ADD_MINMAX(initial_velocity) 51 | #undef ADD_GETSET 52 | 53 | ADD_METHOD(system, clone) 54 | ADD_GC(free_system) 55 | REGISTER_CLASS(system, "System") 56 | END_MODULE() 57 | 58 | -------------------------------------------------------------------------------- /src/audio/music.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include 20 | #include 21 | 22 | typedef struct Music Music; 23 | typedef struct MusicCallback MusicCallback; 24 | 25 | #include "audio.h" 26 | 27 | #define STREAM_NUM_BUFFERS 3 28 | 29 | struct MusicCallback { 30 | unsigned int (*feed_buffer)(MusicCallback *mc, unsigned short *buffer, unsigned int len); 31 | void (*rewind)(MusicCallback *mc); 32 | void (*free)(MusicCallback *mc); 33 | }; 34 | 35 | struct Music { 36 | Source* source; 37 | ALuint alBuffers[STREAM_NUM_BUFFERS]; 38 | bool ended; 39 | bool loop; 40 | MusicCallback* callback; 41 | ALenum format; 42 | int samplesrate; 43 | unsigned int buffersize; 44 | int ref; 45 | int onend_clb; 46 | float pitch; 47 | float volume; 48 | }; 49 | 50 | void music_play(Music *m, bool loop, int onend_clb); 51 | void music_update(Music *m); 52 | void music_stop(Music *m); 53 | void music_pause(Music *m); 54 | void music_free(Music *m); 55 | void music_set_pitch(Music *m, float pitch); 56 | void music_set_volume(Music *m, float volume); 57 | 58 | Music *music_load(MusicCallback* callback, int samplesrate, int num_channels); 59 | Music *music_load_from_file(const char* filename); 60 | 61 | -------------------------------------------------------------------------------- /src/audio/audio.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include 20 | #include 21 | 22 | typedef struct Source Source; 23 | typedef enum SourceType { 24 | SOURCE_MUSIC, 25 | SOURCE_SOUND 26 | } SourceType; 27 | 28 | #include "sound.h" 29 | #include "music.h" 30 | #include "log.h" 31 | 32 | #define DEFAULT_SAMPLES_RATE 44100 33 | 34 | struct Source { 35 | ALuint alSource; 36 | bool used; 37 | bool paused; 38 | union { 39 | Sound* currentSound; 40 | Music* currentMusic; 41 | }; 42 | SourceType type; 43 | float desiredVolume; 44 | }; 45 | 46 | #ifndef NDEBUG 47 | #define audio_check_error() do { \ 48 | ALint error; \ 49 | while ((error = alGetError()) != AL_NO_ERROR) { \ 50 | log_debug("[ALerr] %s", alGetString(error)); \ 51 | } \ 52 | } while (false) 53 | #else 54 | #define audio_check_error() 55 | #endif 56 | 57 | bool audio_init_if_needed(void); 58 | void audio_update(float dt); 59 | void audio_free(void); 60 | 61 | void audio_set_music_volume(float volume); 62 | void audio_set_sound_volume(float volume); 63 | float audio_get_music_volume(void); 64 | float audio_get_sound_volume(void); 65 | bool audio_try_free_sound(Sound* sound); 66 | 67 | Source* audio_get_free_source(void); 68 | 69 | -------------------------------------------------------------------------------- /src/storage/storage_bind.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #include 18 | #include 19 | #ifndef EMSCRIPTEN 20 | #include 21 | #endif 22 | 23 | #include "lua_util.h" 24 | #include "storage_bind.h" 25 | #include "storage.h" 26 | 27 | extern int json_encode(lua_State* L); 28 | extern int json_decode(lua_State* L); 29 | 30 | int mlua_store(lua_State* L) 31 | { 32 | assert(L); 33 | 34 | const char* key = luaL_checkstring(L, 1); 35 | 36 | lua_pushcfunction(L, json_encode); 37 | lua_pushvalue(L, 2); 38 | 39 | call_lua_function(L, 1, 1); // table in param, returns json 40 | 41 | const char* value = luaL_checkstring(L, -1); 42 | 43 | storage_store(key, value); 44 | return 0; 45 | } 46 | 47 | int mlua_fetch(lua_State* L) 48 | { 49 | assert(L); 50 | 51 | const char* key = luaL_checkstring(L, 1); 52 | char* value = storage_fetch(key); 53 | 54 | if (!value || !value[0]) { 55 | #ifndef EMSCRIPTEN 56 | free(value); 57 | #endif 58 | lua_pushnil(L); 59 | return 1; 60 | } 61 | 62 | lua_pushcfunction(L, json_decode); 63 | lua_pushstring(L, value); 64 | call_lua_function(L, 1, 1); 65 | 66 | #ifndef EMSCRIPTEN 67 | free(value); 68 | #endif 69 | // table is returned by json_decode 70 | return 1; 71 | } 72 | 73 | -------------------------------------------------------------------------------- /tests/graphics/precise.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | local w, h = 32, 32 4 | local surface 5 | local image 6 | local image_sprite = {x=16, y=16, w=32, h=32} 7 | function drystal.init() 8 | drystal.resize(800, 600) 9 | drystal.camera.reset() 10 | 11 | image = assert(drystal.load_surface('precise.png')) 12 | image:set_filter(drystal.filters.nearest) 13 | 14 | surface = drystal.new_surface(w, h) 15 | surface:set_filter(drystal.filters.nearest) 16 | surface:draw_on() 17 | drystal.set_color(255, 0, 0) 18 | drystal.draw_rect(0, 0, w, h) 19 | 20 | local s2 = assert(drystal.new_surface(w-2, h-2)) 21 | s2:set_filter(drystal.filters.nearest) 22 | s2:draw_on() 23 | drystal.set_color(0, 255, 0) 24 | drystal.draw_rect(1, 1, w-2, h-2) 25 | 26 | s2:draw_from() 27 | surface:draw_on() 28 | drystal.set_color(255, 255, 255) 29 | drystal.draw_sprite({x=0, y=0, w=w-2, h=h-2}, 1, 1) 30 | 31 | drystal.screen:draw_on() 32 | end 33 | 34 | function drystal.draw() 35 | drystal.set_alpha(255) 36 | drystal.set_color(255, 255, 255) 37 | drystal.draw_background() 38 | 39 | drystal.set_color(0, 0, 0) 40 | drystal.draw_rect(300, 300, 50, 50) 41 | drystal.draw_rect(200, 200, 1, 1) 42 | drystal.draw_rect(204, 204, 2, 2) 43 | 44 | drystal.draw_rect(150-w, 150, w, h) 45 | 46 | surface:draw_from() 47 | drystal.set_color(255, 255, 255) 48 | drystal.draw_sprite({x=0, y=0, w=w, h=h}, 150, 150) 49 | 50 | image:draw_from() 51 | drystal.set_color(255, 255, 255) 52 | drystal.draw_sprite(image_sprite, 150+w, 150) 53 | end 54 | 55 | function drystal.mouse_motion(x, y) 56 | drystal.camera.x = 400 - x 57 | drystal.camera.y = 300 - y 58 | end 59 | function drystal.mouse_press(x, y, b) 60 | if b == drystal.buttons.wheel_up then 61 | drystal.camera.zoom = drystal.camera.zoom * 1.3 62 | elseif b == drystal.buttons.wheel_down then 63 | drystal.camera.zoom = drystal.camera.zoom / 1.3 64 | end 65 | end 66 | 67 | function drystal.key_press(k) 68 | if k == 'a' then 69 | drystal.stop() 70 | end 71 | end 72 | 73 | -------------------------------------------------------------------------------- /src/physics/body_bind.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include "lua_util.h" 20 | 21 | struct lua_State; 22 | class b2Body; 23 | 24 | struct Body { 25 | b2Body* body; 26 | Body* nextdestroy; 27 | bool getting_destroyed; 28 | int ref; 29 | }; 30 | 31 | DECLARE_PUSHPOP(Body, body) 32 | Body* pop_body_secure(lua_State* L, int index); 33 | 34 | int mlua_get_center_position_body(lua_State* L); 35 | int mlua_set_active_body(lua_State* L); 36 | int mlua_set_bullet_body(lua_State* L); 37 | int mlua_get_mass_body(lua_State* L); 38 | int mlua_set_mass_center_body(lua_State* L); 39 | int mlua_apply_force_body(lua_State* L); 40 | int mlua_apply_linear_impulse_body(lua_State* L); 41 | int mlua_apply_angular_impulse_body(lua_State* L); 42 | int mlua_apply_torque_body(lua_State* L); 43 | int mlua_dump_body(lua_State* L); 44 | int mlua_free_body(lua_State* L); 45 | 46 | #define __BODY_GET_SET(value) \ 47 | int mlua_set_##value##_body(lua_State* L); \ 48 | int mlua_get_##value##_body(lua_State* L); 49 | 50 | __BODY_GET_SET(position) 51 | __BODY_GET_SET(linear_velocity) 52 | __BODY_GET_SET(angle) 53 | __BODY_GET_SET(angular_velocity) 54 | __BODY_GET_SET(linear_damping) 55 | __BODY_GET_SET(angular_damping) 56 | __BODY_GET_SET(linearvelocity) 57 | __BODY_GET_SET(fixed_rotation) 58 | 59 | #undef __BODY_GET_SET 60 | 61 | -------------------------------------------------------------------------------- /src/lua_util.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "engine.h" 24 | #include "lua_util.h" 25 | #include "util.h" 26 | #include "livecoding.h" 27 | #include "log.h" 28 | 29 | log_category("lua"); 30 | 31 | int traceback(lua_State *L) 32 | { 33 | lua_getglobal(L, "debug"); 34 | lua_getfield(L, -1, "newtraceback"); 35 | lua_insert(L, 1); 36 | lua_pop(L, 1); 37 | 38 | lua_pushinteger(L, 1); 39 | lua_pushboolean(L, stderr_use_colors()); 40 | 41 | lua_call(L, lua_gettop(L) - 1, 1); 42 | fprintf(stderr, "%s\n", lua_tostring(L, -1)); 43 | return 0; 44 | } 45 | 46 | void call_lua_function(lua_State *L, int num_args, int num_ret) 47 | { 48 | assert(L); 49 | assert(num_args >= 0); 50 | assert(num_ret >= 0); 51 | 52 | #ifdef EMSCRIPTEN 53 | lua_call(L, num_args, num_ret); 54 | #else 55 | /* from lua/src/lua.c */ 56 | int base = lua_gettop(L) - num_args; 57 | lua_pushcfunction(L, traceback); 58 | lua_insert(L, base); 59 | if (lua_pcall(L, num_args, num_ret, base)) { 60 | #ifdef BUILD_LIVECODING 61 | if (livecoding_is_running()) { 62 | engine_wait_next_reload(); 63 | lua_pop(L, 1); 64 | } else 65 | #endif 66 | { 67 | engine_free(); 68 | exit(EXIT_FAILURE); 69 | } 70 | } 71 | lua_remove(L, base); 72 | #endif 73 | } 74 | 75 | -------------------------------------------------------------------------------- /external/libpngCMakeLists.cmake: -------------------------------------------------------------------------------- 1 | set(PNGLIB_MAJOR 1) 2 | set(PNGLIB_MINOR 6) 3 | set(PNGLIB_RELEASE 17) 4 | set(PNGLIB_NAME libpng${PNGLIB_MAJOR}${PNGLIB_MINOR}) 5 | set(PNGLIB_VERSION ${PNGLIB_MAJOR}.${PNGLIB_MINOR}.${PNGLIB_RELEASE}) 6 | 7 | set(ZLIB_LIBRARY zlib) 8 | set(ZLIB_INCLUDE_DIR ../zlib/) 9 | 10 | # SET LIBNAME 11 | set(PNG_LIB_NAME png${PNGLIB_MAJOR}${PNGLIB_MINOR}) 12 | set(PNG_LIBRARY ${PNG_LIB_NAME} PARENT_SCOPE) 13 | 14 | # Use the prebuilt pnglibconf.h file from the scripts folder 15 | # TODO: fix this by building with awk; without this no cmake build can be 16 | # configured directly (to do so indirectly use your local awk to build a 17 | # pnglibconf.h in the build directory.) 18 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libpng/scripts/pnglibconf.h.prebuilt 19 | ${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h) 20 | include_directories(${CMAKE_CURRENT_BINARY_DIR}) 21 | 22 | set(libpng_public_hdrs 23 | libpng/png.h 24 | libpng/pngconf.h 25 | ${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h 26 | ) 27 | set(libpng_sources 28 | ${libpng_public_hdrs} 29 | libpng/pngdebug.h 30 | libpng/pnginfo.h 31 | libpng/pngpriv.h 32 | libpng/pngstruct.h 33 | libpng/png.c 34 | libpng/pngerror.c 35 | libpng/pngget.c 36 | libpng/pngmem.c 37 | libpng/pngpread.c 38 | libpng/pngread.c 39 | libpng/pngrio.c 40 | libpng/pngrtran.c 41 | libpng/pngrutil.c 42 | libpng/pngset.c 43 | libpng/pngtrans.c 44 | libpng/pngwio.c 45 | libpng/pngwrite.c 46 | libpng/pngwtran.c 47 | libpng/pngwutil.c 48 | ) 49 | 50 | # NOW BUILD OUR TARGET 51 | include_directories("${CMAKE_CURRENT_SOURCE_DIR}/libpng/" ${ZLIB_INCLUDE_DIR}) 52 | 53 | add_library(${PNG_LIB_NAME} STATIC ${libpng_sources}) 54 | target_link_libraries(${PNG_LIB_NAME} ${ZLIB_LIBRARY} ${M_LIBRARY}) 55 | 56 | # Ensure the CMAKE_LIBRARY_OUTPUT_DIRECTORY is set 57 | IF(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY) 58 | SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "lib") 59 | ENDIF(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY) 60 | 61 | set_target_properties(${PNG_LIB_NAME_STATIC} PROPERTIES 62 | OUTPUT_NAME ${PNG_LIB_NAME} 63 | CLEAN_DIRECT_OUTPUT 1) 64 | -------------------------------------------------------------------------------- /tests/particle/smoke.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | tex = drystal.load_surface('spritesheet.png') 4 | local sys_smoke = drystal.new_system(200, 596) 5 | 6 | sys_smoke:set_sizes { 7 | [0]=100, 8 | [0.25] = 75, 9 | [0.5] = 55, 10 | [1] = 25, 11 | } 12 | sys_smoke:set_colors { 13 | [0]=drystal.colors.white, 14 | [0.4]=drystal.colors.gray, 15 | [0.7]=drystal.colors.gray:darker(), 16 | [1]='black', 17 | } 18 | sys_smoke:set_alphas { 19 | [0]=20, 20 | [0.2]=100, 21 | [1]=0, 22 | } 23 | 24 | sys_smoke:set_lifetime(3) 25 | sys_smoke:set_direction(-math.pi / 2 - math.pi/8, -math.pi/2 + math.pi/8) 26 | sys_smoke:set_initial_velocity(100, 150) 27 | sys_smoke:set_initial_acceleration(0) 28 | sys_smoke:set_offset(-10, 20, 0, 10) 29 | sys_smoke:set_emission_rate(16) 30 | sys_smoke:set_texture(tex, 0, 0) 31 | 32 | local sys_smoke_opaque = drystal.new_system(600, 600) 33 | 34 | sys_smoke_opaque:set_sizes { 35 | [0]=100, 36 | [0.25] = 75, 37 | [0.5] = 55, 38 | [1] = 25, 39 | } 40 | sys_smoke_opaque:set_colors { 41 | [0]=drystal.colors.white, 42 | [0.4]=drystal.colors.white:darker(), 43 | [0.9]='black', 44 | } 45 | 46 | sys_smoke_opaque:set_lifetime(3) 47 | sys_smoke_opaque:set_direction(-math.pi / 2 - math.pi/8, -math.pi/2 + math.pi/8) 48 | sys_smoke_opaque:set_initial_velocity(100, 150) 49 | sys_smoke_opaque:set_initial_acceleration(0) 50 | sys_smoke_opaque:set_emission_rate(25) 51 | sys_smoke_opaque:set_texture(tex, 0, 0) 52 | 53 | function drystal.init() 54 | drystal.resize(800, 600) 55 | sys_smoke:start() 56 | sys_smoke_opaque:start() 57 | end 58 | 59 | function drystal.update(dt) 60 | if dt > .06 then 61 | dt = .06 62 | end 63 | sys_smoke:update(dt) 64 | sys_smoke_opaque:update(dt) 65 | end 66 | 67 | function drystal.draw() 68 | drystal.set_blend_mode(drystal.blends.default) 69 | drystal.set_color('black') 70 | drystal.set_alpha(255) 71 | drystal.draw_background() 72 | 73 | sys_smoke_opaque:draw() 74 | 75 | drystal.set_blend_mode(drystal.blends.add) 76 | sys_smoke:draw() 77 | end 78 | 79 | function drystal.key_press(k) 80 | if k == 'a' then 81 | drystal.stop() 82 | end 83 | end 84 | 85 | -------------------------------------------------------------------------------- /src/graphics/shader.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #define GL_GLEXT_PROTOTYPES 20 | #ifndef EMSCRIPTEN 21 | #include 22 | #else 23 | #include 24 | #endif 25 | 26 | typedef struct Shader Shader; 27 | 28 | extern const char* SHADER_PREFIX; 29 | extern const char* DEFAULT_VERTEX_SHADER; 30 | extern const char* DEFAULT_FRAGMENT_SHADER_COLOR; 31 | extern const char* DEFAULT_FRAGMENT_SHADER_TEX; 32 | 33 | typedef enum AttrLocationIndex { 34 | // WebGL wants 0 as an attribute, so here it is 35 | ATTR_LOCATION_POSITION = 0, 36 | ATTR_LOCATION_COLOR, 37 | ATTR_LOCATION_TEXCOORD, 38 | } AttrLocationIndex; 39 | 40 | enum VarLocationIndex { 41 | VAR_LOCATION_COLOR, 42 | VAR_LOCATION_TEX, 43 | }; 44 | typedef enum VarLocationIndex VarLocationIndex; 45 | 46 | struct Shader { 47 | GLuint prog_color; 48 | GLuint prog_tex; 49 | GLuint vert; 50 | GLuint frag_color; 51 | GLuint frag_tex; 52 | 53 | struct { 54 | GLuint dxLocation; 55 | GLuint dyLocation; 56 | GLuint zoomLocation; 57 | GLuint rotationMatrixLocation; 58 | GLuint destinationSizeLocation; 59 | GLuint sourceSizeLocation; 60 | } vars[2]; 61 | int ref; 62 | 63 | }; 64 | Shader *shader_new(GLuint prog_color, GLuint prog_tex, GLuint vert, GLuint frag_color, GLuint frag_tex); 65 | void shader_free(Shader *s); 66 | 67 | void shader_feed(const Shader *s, const char* name, float value); 68 | 69 | -------------------------------------------------------------------------------- /src/log.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #include 24 | 25 | #include "macro.h" 26 | #include "util.h" 27 | 28 | typedef enum LogLevel 29 | { 30 | LOG_ERROR, 31 | LOG_WARNING, 32 | LOG_INFO, 33 | LOG_DEBUG, 34 | } LogLevel; 35 | 36 | /* 37 | * Before using the logging API you must call log_category() at the beginning 38 | * of your file, like this: 39 | * log_category("display"); 40 | * [...] 41 | * if (r < 0) { 42 | * log_error("an error happenned""); 43 | * } 44 | */ 45 | #define log_category(cat) \ 46 | static _unused_ const char *_log_category = cat 47 | 48 | void log_internal(LogLevel level, const char *category, const char *format, ...) _printf_(3,4); 49 | 50 | #ifndef NDEBUG 51 | #define log_debug(msg, ...) \ 52 | log_internal(LOG_DEBUG, _log_category, "[%s:%d %s()] " msg, __FILE__, __LINE__, __func__, ##__VA_ARGS__) 53 | #define log_info(msg, ...) \ 54 | log_internal(LOG_INFO, _log_category, msg, ##__VA_ARGS__) 55 | #else 56 | #define log_debug(msg, ...) 57 | #define log_info(msg, ...) 58 | #endif 59 | 60 | #define log_warning(msg, ...) \ 61 | log_internal(LOG_WARNING, _log_category, msg, ##__VA_ARGS__) 62 | 63 | #define log_error(msg, ...) \ 64 | log_internal(LOG_ERROR, _log_category, msg, ##__VA_ARGS__) 65 | 66 | __attribute__((noreturn)) void log_oom_and_exit(void); 67 | 68 | #ifdef __cplusplus 69 | } 70 | #endif 71 | 72 | -------------------------------------------------------------------------------- /src/log.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #include 18 | #include 19 | #include 20 | 21 | #include "log.h" 22 | 23 | _printf_(3, 0) static void log_message(const char *level, const char *category, const char *format, va_list ap) 24 | { 25 | fprintf(stderr, "[%s|%10s] ", level, category); 26 | vfprintf(stderr, format, ap); 27 | fprintf(stderr, "\n"); 28 | } 29 | 30 | _printf_(3, 0) static void log_internalv(LogLevel level, const char *category, const char *format, va_list ap) 31 | { 32 | switch (level) { 33 | case LOG_ERROR: 34 | log_message(stderr_use_colors() ? ANSI_HIGHLIGHT_RED_ON "ERR " ANSI_RESET : "ERR ", category, format, ap); 35 | break; 36 | case LOG_WARNING: 37 | log_message(stderr_use_colors() ? ANSI_HIGHLIGHT_YELLOW_ON "WARN" ANSI_RESET : "WARN", category, format, ap); 38 | break; 39 | case LOG_INFO: 40 | log_message(stderr_use_colors() ? ANSI_HIGHLIGHT_ON "INFO" ANSI_RESET : "INFO", category, format, ap); 41 | break; 42 | case LOG_DEBUG: 43 | log_message(stderr_use_colors() ? ANSI_HIGHLIGHT_GRAY_ON "DBG " ANSI_RESET : "DBG ", category, format, ap); 44 | break; 45 | } 46 | } 47 | 48 | void log_oom_and_exit(void) 49 | { 50 | fprintf(stderr, "Out of memory. Exiting."); 51 | exit(EXIT_FAILURE); 52 | } 53 | 54 | void log_internal(LogLevel level, const char *category, const char *format, ...) 55 | { 56 | va_list ap; 57 | 58 | va_start(ap, format); 59 | log_internalv(level, category, format, ap); 60 | va_end(ap); 61 | } 62 | -------------------------------------------------------------------------------- /src/graphics/sprite.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | local Sprite = { 4 | x=0, 5 | y=0, 6 | angle=0, 7 | w=0, 8 | h=0, 9 | source=nil, 10 | color={255, 255, 255}, 11 | alpha=255, 12 | } 13 | local sprite_is_update_with = { 14 | x=true, 15 | y=true, 16 | w=true, 17 | h=true, 18 | angle=true, 19 | source=true, 20 | } 21 | Sprite.__index = function(self, key) 22 | return rawget(self.data, key) or rawget(self, key) or rawget(Sprite, key) 23 | end 24 | Sprite.__newindex = function(self, key, value) 25 | if sprite_is_update_with[key] then 26 | rawset(self.data, key, value) 27 | self._updated = true 28 | else 29 | rawset(self, key, value) 30 | end 31 | end 32 | 33 | drystal.Sprite = Sprite 34 | 35 | function drystal.new_sprite(source, x, y, w, h) 36 | local sprite = setmetatable({data={}}, Sprite) 37 | sprite.source = source 38 | sprite.data.x = x or 0 39 | sprite.data.y = y or 0 40 | sprite.data.w = w or source.w 41 | sprite.data.h = h or source.h 42 | return sprite 43 | end 44 | 45 | function Sprite:_update() 46 | local cos = math.cos(self.angle) 47 | local sin = math.sin(self.angle) 48 | local x = self.x 49 | local y = self.y 50 | local w = self.w 51 | local h = self.h 52 | local function rot(_x, _y) 53 | return x + _x*cos - _y*sin + w/2, 54 | y + _y*cos + _x*sin + h/2 55 | end 56 | self._x1, self._y1 = rot(-w/2, -h/2) 57 | self._x2, self._y2 = rot(w/2, -h/2) 58 | self._x3, self._y3 = rot(w/2, h/2) 59 | self._x4, self._y4 = rot(-w/2, h/2) 60 | self._updated = false 61 | end 62 | 63 | function Sprite:draw() 64 | drystal.set_color(self.color) 65 | drystal.set_alpha(self.alpha) 66 | if self._updated then 67 | self:_update() 68 | end 69 | 70 | local x1, y1 = self._x1, self._y1 71 | local x2, y2 = self._x2, self._y2 72 | local x3, y3 = self._x3, self._y3 73 | local x4, y4 = self._x4, self._y4 74 | local xi = self.source.x 75 | local yi = self.source.y 76 | local xi2 = self.source.x + self.source.w 77 | local yi2 = self.source.y + self.source.h 78 | 79 | if self.w < 0 then 80 | xi, xi2 = xi2, xi 81 | end 82 | if self.h < 0 then 83 | yi, yi2 = yi2, yi 84 | end 85 | 86 | drystal.draw_quad(xi, yi, xi2, yi, xi2, yi2, xi, yi2, 87 | x1, y1, x2, y2, x3, y3, x4, y4) 88 | end 89 | 90 | -------------------------------------------------------------------------------- /src/build.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #ifdef BUILD_AUDIO 20 | #define _AUDIO_FEATURE_ "+AUDIO" 21 | #else 22 | #define _AUDIO_FEATURE_ "-AUDIO" 23 | #endif 24 | 25 | #ifdef BUILD_FONT 26 | #define _FONT_FEATURE_ "+FONT" 27 | #else 28 | #define _FONT_FEATURE_ "-FONT" 29 | #endif 30 | 31 | #ifdef BUILD_GRAPHICS 32 | #define _GRAPHICS_FEATURE_ "+GRAPHICS" 33 | #else 34 | #define _GRAPHICS_FEATURE_ "-GRAPHICS" 35 | #endif 36 | 37 | #ifdef BUILD_LIVECODING 38 | #define _LIVECODING_FEATURE_ "+LIVECODING" 39 | #else 40 | #define _LIVECODING_FEATURE_ "-LIVECODING" 41 | #endif 42 | 43 | #ifdef BUILD_PHYSICS 44 | #define _PHYSICS_FEATURE_ "+PHYSICS" 45 | #else 46 | #define _PHYSICS_FEATURE_ "-PHYSICS" 47 | #endif 48 | 49 | #ifdef BUILD_PARTICLE 50 | #define _PARTICLE_FEATURE_ "+PARTICLE" 51 | #else 52 | #define _PARTICLE_FEATURE_ "-PARTICLE" 53 | #endif 54 | 55 | #ifdef BUILD_STORAGE 56 | #define _STORAGE_FEATURE_ "+STORAGE" 57 | #else 58 | #define _STORAGE_FEATURE_ "-STORAGE" 59 | #endif 60 | 61 | #ifdef BUILD_UTILS 62 | #define _UTILS_FEATURE_ "+UTILS" 63 | #else 64 | #define _UTILS_FEATURE_ "-UTILS" 65 | #endif 66 | 67 | #ifdef BUILD_WEB 68 | #define _WEB_FEATURE_ "+WEB" 69 | #else 70 | #define _WEB_FEATURE_ "-WEB" 71 | #endif 72 | 73 | #define DRYSTAL_FEATURES \ 74 | _AUDIO_FEATURE_ " " \ 75 | _FONT_FEATURE_ " " \ 76 | _GRAPHICS_FEATURE_ " " \ 77 | _LIVECODING_FEATURE_ " " \ 78 | _PHYSICS_FEATURE_ " " \ 79 | _PARTICLE_FEATURE_ " " \ 80 | _STORAGE_FEATURE_ " " \ 81 | _UTILS_FEATURE_ " " \ 82 | _WEB_FEATURE_ " " 83 | -------------------------------------------------------------------------------- /src/graphics/camera.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #include 18 | #include 19 | 20 | #include "camera.h" 21 | #include "util.h" 22 | 23 | #define CAMERA_STACK_SIZE (64) 24 | static Camera cameraStack[CAMERA_STACK_SIZE]; 25 | static size_t cameraStackIndex; 26 | 27 | Camera *camera_new() 28 | { 29 | Camera *c = new0(Camera, 1); 30 | c->zoom = 1; 31 | 32 | return c; 33 | } 34 | 35 | void camera_free(Camera *c) 36 | { 37 | if (!c) 38 | return; 39 | 40 | free(c); 41 | } 42 | 43 | void camera_update_matrix(Camera *c, int width, int height) 44 | { 45 | float ratio; 46 | float angle; 47 | 48 | assert(c); 49 | assert(width > 0); 50 | assert(height > 0); 51 | 52 | angle = c->angle; 53 | ratio = (float) width / height; 54 | c->matrix[0] = cosf(angle); 55 | c->matrix[1] = sinf(angle) * ratio; 56 | c->matrix[2] = -sinf(angle) / ratio; 57 | c->matrix[3] = cosf(angle); 58 | } 59 | 60 | void camera_reset(Camera *c) 61 | { 62 | assert(c); 63 | 64 | c->dx = 0; 65 | c->dy = 0; 66 | c->angle = 0; 67 | c->zoom = 1; 68 | } 69 | 70 | void camera_push(Camera *c) 71 | { 72 | assert(c); 73 | assert(!camera_stack_is_full()); 74 | 75 | cameraStack[cameraStackIndex++] = *c; 76 | } 77 | 78 | void camera_pop(Camera *c) 79 | { 80 | assert(c); 81 | assert(!camera_stack_is_empty()); 82 | 83 | *c = cameraStack[--cameraStackIndex]; 84 | } 85 | 86 | bool camera_stack_is_full(void) 87 | { 88 | return cameraStackIndex == CAMERA_STACK_SIZE; 89 | } 90 | 91 | bool camera_stack_is_empty(void) 92 | { 93 | return cameraStackIndex == 0; 94 | } 95 | 96 | -------------------------------------------------------------------------------- /src/particle/system_bind.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include 20 | 21 | #include "lua_util.h" 22 | #include "system.h" 23 | 24 | DECLARE_PUSHPOP(System, system) 25 | 26 | int mlua_new_system(lua_State* L); 27 | int mlua_set_position_system(lua_State* L); 28 | int mlua_get_position_system(lua_State* L); 29 | int mlua_set_offset_system(lua_State* L); 30 | int mlua_get_offset_system(lua_State* L); 31 | int mlua_update_system(lua_State* L); 32 | int mlua_draw_system(lua_State* L); 33 | int mlua_add_size_system(lua_State* L); 34 | int mlua_add_color_system(lua_State* L); 35 | int mlua_add_alpha_system(lua_State* L); 36 | int mlua_clear_sizes_system(lua_State* L); 37 | int mlua_clear_colors_system(lua_State* L); 38 | int mlua_clear_alphas_system(lua_State* L); 39 | int mlua_set_texture_system(lua_State* L); 40 | int mlua_clone_system(lua_State* L); 41 | int mlua_free_system(lua_State* L); 42 | 43 | #define __SYSTEM_GET_SET(attr) \ 44 | int mlua_get_##attr##_system(lua_State* L); \ 45 | int mlua_set_##attr##_system(lua_State* L); 46 | 47 | __SYSTEM_GET_SET(min_lifetime) 48 | __SYSTEM_GET_SET(max_lifetime) 49 | __SYSTEM_GET_SET(min_direction) 50 | __SYSTEM_GET_SET(max_direction) 51 | __SYSTEM_GET_SET(min_initial_acceleration) 52 | __SYSTEM_GET_SET(max_initial_acceleration) 53 | __SYSTEM_GET_SET(min_initial_velocity) 54 | __SYSTEM_GET_SET(max_initial_velocity) 55 | __SYSTEM_GET_SET(emission_rate) 56 | 57 | #undef __SYSTEM_GET_SET 58 | 59 | #define __ACTION(action) \ 60 | int mlua_##action##_system(lua_State* L); 61 | __ACTION(emit) 62 | __ACTION(start) 63 | __ACTION(stop) 64 | __ACTION(reset) 65 | 66 | #undef __ACTION 67 | 68 | -------------------------------------------------------------------------------- /tests/particle/simple.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | local sys1 = drystal.new_system(200, 300, 5) 4 | sys1:add_size(0, 6) 5 | sys1:add_size(1, 6) 6 | sys1:add_color(0, 0, 255, 0, 255, 0, 255) 7 | sys1:add_color(1, 0, 255, 0, 255, 0, 255) 8 | local running 9 | 10 | local scrolling = false 11 | local scrollx, scrolly = 0, 0 12 | 13 | local systems = { 14 | drystal.new_system(400, 300), 15 | } 16 | 17 | function drystal.init() 18 | drystal.resize(600, 600) 19 | sys1:start() 20 | running = true 21 | for _, s in ipairs(systems) do 22 | s:start() 23 | end 24 | end 25 | 26 | function drystal.update(dt) 27 | if dt > .06 then 28 | dt = .06 29 | end 30 | sys1:update(dt) 31 | for _, s in ipairs(systems) do 32 | s:update(dt) 33 | end 34 | end 35 | 36 | function drystal.draw() 37 | drystal.set_color(0, 0, 0) 38 | drystal.draw_background() 39 | 40 | sys1:draw(scrollx, scrolly) 41 | for _, s in ipairs(systems) do 42 | s:draw(scrollx, scrolly) 43 | end 44 | end 45 | 46 | function drystal.mouse_motion(x, y, dx, dy) 47 | sys1:set_position(x - scrollx, y - scrolly) 48 | if scrolling then 49 | scrollx = scrollx + dx 50 | scrolly = scrolly + dy 51 | end 52 | end 53 | 54 | function drystal.mouse_press(x, y, b) 55 | if b == drystal.buttons.left then 56 | local s = drystal.new_system(x - scrollx, y - scrolly) 57 | s:set_direction(0, math.pi/2) 58 | s:add_size(0, 6) 59 | s:add_size(1, 6) 60 | s:add_color(0, 0, 0, 0) 61 | s:add_color(1, 255, 255, 255) 62 | s:start() 63 | table.insert(systems, s) 64 | local s = s:clone() 65 | s:set_direction(math.pi, math.pi + math.pi/2) 66 | table.insert(systems, s) 67 | elseif b == drystal.buttons.right then 68 | scrolling = true 69 | elseif b == drystal.buttons.wheel_up then 70 | sys1:set_emission_rate(sys1:get_emission_rate() + 1) 71 | elseif b == drystal.buttons.wheel_down then 72 | sys1:set_emission_rate(sys1:get_emission_rate() - 1) 73 | end 74 | end 75 | 76 | function drystal.mouse_release(_, _, b) 77 | if b == drystal.buttons.right then 78 | scrolling = false 79 | end 80 | end 81 | 82 | function drystal.key_press(k) 83 | if k == 'space' then 84 | if running then 85 | sys1:stop() 86 | else 87 | sys1:start() 88 | end 89 | running = not running 90 | elseif k == 'c' then 91 | systems = {} 92 | elseif k == 'a' then 93 | drystal.stop() 94 | end 95 | end 96 | 97 | -------------------------------------------------------------------------------- /cmake/GenerateLuaFiles.cmake: -------------------------------------------------------------------------------- 1 | # put all .lua files into a single .cpp files 2 | # the function load_luafiles runs those codes and return 1 if success 3 | set(LUAFILES_LIST "drystal.lua" "traceback.lua") 4 | if(BUILD_WEB) 5 | list(APPEND LUAFILES_LIST "web/web.lua") 6 | endif() 7 | if(BUILD_PARTICLE) 8 | list(APPEND LUAFILES_LIST "particle/particle.lua") 9 | endif() 10 | if(BUILD_PHYSICS) 11 | list(APPEND LUAFILES_LIST "physics/raycast.lua") 12 | endif() 13 | if(BUILD_GRAPHICS) 14 | list(APPEND LUAFILES_LIST "graphics/postfx.lua" "graphics/draw.lua" "graphics/sprite.lua" "graphics/colors.lua") 15 | endif() 16 | if(BUILD_LIVECODING) 17 | list(APPEND LUAFILES_LIST "reload.lua") 18 | endif() 19 | 20 | set(LUAFILES_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/luafiles.c) 21 | 22 | # generate luafiles.c 23 | file(WRITE ${LUAFILES_OUTPUT} " 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include \"luafiles.h\" 30 | #include \"lua_util.h\" 31 | #include \"log.h\" 32 | log_category(\"luafiles\"); 33 | 34 | int load_luafiles(lua_State* L, int traceback_index) 35 | { 36 | (void) L;") 37 | foreach (luacode ${LUAFILES_LIST}) 38 | file(READ ${luacode} FILE_CONTENT) 39 | get_filename_component(luacode_short ${luacode} NAME) 40 | # \\ => \\\\ 41 | string(REGEX REPLACE "\\\\\\\\" "\\\\\\\\\\\\\\\\" FILE_CONTENT "${FILE_CONTENT}") 42 | # \n => \\n 43 | string(REGEX REPLACE "\\\\\\n" "\\\\\\\\n" FILE_CONTENT "${FILE_CONTENT}") 44 | # " => \" 45 | string(REGEX REPLACE "\\\"" "\\\\\"" FILE_CONTENT "${FILE_CONTENT}") 46 | # => \n\ 47 | string(REGEX REPLACE "\n" "\\\\n\\\\\n" FILE_CONTENT "${FILE_CONTENT}") 48 | file(APPEND ${LUAFILES_OUTPUT} " 49 | { 50 | const char* file = \"${luacode_short}\"; 51 | const char* code = \"${FILE_CONTENT}\"; 52 | if (luaL_loadbuffer(L, code, strlen(code), file)) { 53 | log_error(\"%s\", lua_tostring(L, -1)); 54 | return 0; 55 | } 56 | if (lua_pcall(L, 0, 0, traceback_index)) { 57 | return 0; 58 | } 59 | } 60 | ") 61 | endforeach (luacode) 62 | file(APPEND ${LUAFILES_OUTPUT} " 63 | return 1; 64 | }") 65 | 66 | add_custom_command( 67 | OUTPUT ${LUAFILES_OUTPUT} 68 | COMMAND cmake .. # re-run code generation 69 | DEPENDS ${LUAFILES_LIST} 70 | VERBATIM) 71 | list(APPEND SOURCES ${LUAFILES_OUTPUT}) 72 | 73 | -------------------------------------------------------------------------------- /tests/graphics/buffer.lua: -------------------------------------------------------------------------------- 1 | local drystal = require "drystal" 2 | 3 | -- test sizes 4 | buffer = drystal.new_buffer(6) 5 | buffer:use() 6 | drystal.draw_point(1,1,4) 7 | drystal.draw_point(1,1,4) 8 | drystal.draw_point(1,1,4) 9 | drystal.draw_point(1,1,4) 10 | drystal.draw_point(1,1,4) 11 | drystal.draw_point(1,1,4) 12 | 13 | buffer = assert(drystal.new_buffer(4)) 14 | buffer:use() 15 | drystal.draw_line(1,1,1,1) 16 | drystal.draw_line(1,1,1,1) 17 | 18 | buffer = assert(drystal.new_buffer(10)) 19 | buffer:use() 20 | drystal.draw_triangle(1,1,1,1,1,1) 21 | drystal.draw_triangle(1,1,1,1,1,1) 22 | drystal.draw_triangle(1,1,1,1,1,1) 23 | 24 | drystal.use_default_buffer() 25 | 26 | local spritesheet = assert(drystal.fromjson(io.open('image.json'):read('*all'))) 27 | 28 | function drystal.init() 29 | drystal.resize(600, 400) 30 | image = assert(drystal.load_surface(spritesheet.meta.image)) 31 | image:draw_from() 32 | print('b to toggle buffer') 33 | end 34 | 35 | local bufferize = true 36 | local buffer 37 | local number = 3000 38 | local tick = 0 39 | function drystal.draw() 40 | tick = tick + 1 41 | 42 | drystal.set_alpha(255) 43 | drystal.set_color(10, 10, 30) 44 | drystal.draw_background() 45 | 46 | local sprite = spritesheet.frames['character.png'].frame 47 | drystal.set_color(0, 255, 0) 48 | drystal.set_alpha(255) 49 | drystal.draw_sprite(sprite, 300, 200) 50 | 51 | drystal.set_color(255, 0, 0) 52 | drystal.set_alpha(105) 53 | 54 | if bufferize then 55 | if not buffer then 56 | buffer = assert(drystal.new_buffer(number * 6 / 2)) 57 | buffer:use() 58 | heavy_draw(number) 59 | buffer:upload_and_free() 60 | drystal.use_default_buffer() 61 | end 62 | buffer:draw(math.sin(tick/10)*sprite.w) 63 | else 64 | heavy_draw(number) 65 | end 66 | 67 | drystal.set_color(255, 0, 0) 68 | drystal.set_alpha(255) 69 | drystal.draw_sprite(sprite, 332, 200) 70 | drystal.draw_line(0, 0, 600, 400) 71 | end 72 | 73 | function heavy_draw(number) 74 | local sprite = spritesheet.frames['character.png'].frame 75 | for x = 0, number-1 do 76 | drystal.set_color(200, 200, 200) 77 | drystal.set_alpha(255) 78 | drystal.draw_sprite(sprite, x, (x%30)*30) 79 | end 80 | end 81 | 82 | function drystal.key_press(key) 83 | if key == 'a' then 84 | drystal.stop() 85 | elseif key == 'b' then 86 | bufferize = not bufferize 87 | elseif key == 'f' then 88 | drystal.set_fullscreen(true) 89 | end 90 | end 91 | 92 | -------------------------------------------------------------------------------- /src/drystal.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | function drystal.file_exists(name) 4 | local f = io.open(name, "r") 5 | if f then 6 | f:close(f) 7 | return true 8 | end 9 | return false 10 | end 11 | 12 | local function remove_userpackages() 13 | local keep = { 14 | _G=true, 15 | coroutine=true, 16 | table=true, 17 | io=true, 18 | os=true, 19 | string=true, 20 | utf8=true, 21 | bit32=true, 22 | math=true, 23 | debug=true, 24 | package=true, 25 | drystal=true, 26 | } 27 | for name, value in pairs(package.loaded) do 28 | if not keep[name] then 29 | package.loaded[name] = nil 30 | end 31 | end 32 | end 33 | function drystal.reload() 34 | if drystal.prereload then 35 | drystal.prereload() 36 | end 37 | remove_userpackages() 38 | local ok = drystal._load_code() 39 | if ok then 40 | if drystal.init then 41 | drystal.init() 42 | end 43 | if drystal.postreload then 44 | drystal.postreload() 45 | end 46 | end 47 | collectgarbage() 48 | return ok 49 | end 50 | 51 | function table.print(t) 52 | local str = {} 53 | for k, v in pairs(t) do 54 | table.insert(str, ('%s=%s'):format(k, v)) 55 | end 56 | print(table.concat(str, ',')) 57 | end 58 | 59 | function math.distance(x1, y1, x2, y2) 60 | return math.sqrt(math.pow(x1 - x2, 2) + math.pow(y1 - y2, 2)) 61 | end 62 | 63 | function math.clamp(v, min, max) 64 | return math.min(math.max(v, min), max) 65 | end 66 | 67 | function math.aabb(o1, o2) 68 | local x1 = o1.x 69 | local y1 = o1.y 70 | local x2 = o2.x 71 | local y2 = o2.y 72 | return x2 <= x1 + o1.w 73 | and x2 + o2.w >= x1 74 | and y2 <= y1 + o1.h 75 | and y2 + o2.h >= y1 76 | end 77 | 78 | function math.inside(o, x, y) 79 | local xo = o.x 80 | local yo = o.y 81 | return x >= xo and y >= yo 82 | and x < xo + o.w and y < yo + o.h 83 | end 84 | 85 | drystal.Timer = { 86 | time=0, 87 | update=function(self, dt) 88 | if self.finished then return end 89 | self.time = self.time + dt 90 | if self.time >= self.duration then 91 | self.finished = true 92 | if self.callback then 93 | self.callback() 94 | end 95 | end 96 | end, 97 | } 98 | drystal.Timer.__index = drystal.Timer 99 | function drystal.new_timer(duration, callback) 100 | return setmetatable({ 101 | duration=duration, 102 | callback=callback, 103 | }, drystal.Timer) 104 | end 105 | 106 | -------------------------------------------------------------------------------- /src/macro.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) 24 | #define BEGIN_DISABLE_WARNINGS \ 25 | _Pragma("GCC diagnostic push") 26 | 27 | #define DISABLE_WARNING_EFFCPP \ 28 | _Pragma("GCC diagnostic ignored \"-Weffc++\"") 29 | #define DISABLE_WARNING_STRICT_ALIASING \ 30 | _Pragma("GCC diagnostic ignored \"-Wstrict-aliasing\"") 31 | 32 | #define END_DISABLE_WARNINGS \ 33 | _Pragma("GCC diagnostic pop") 34 | #else 35 | #ifdef __clang__ 36 | #define BEGIN_DISABLE_WARNINGS \ 37 | _Pragma("clang diagnostic push") 38 | 39 | #define DISABLE_WARNING_EFFCPP \ 40 | _Pragma("clang diagnostic ignored \"-Weffc++\"") 41 | #define DISABLE_WARNING_STRICT_ALIASING \ 42 | _Pragma("clang diagnostic ignored \"-Wstrict-aliasing\"") 43 | 44 | #define END_DISABLE_WARNINGS \ 45 | _Pragma("clang diagnostic pop") 46 | #else 47 | #define BEGIN_DISABLE_WARNINGS 48 | #define DISABLE_WARNING_EFFCPP 49 | #define DISABLE_WARNING_STRICT_ALIASING 50 | #define END_DISABLE_WARNINGS 51 | #endif 52 | #endif 53 | 54 | #define _malloc_ __attribute__ ((malloc)) 55 | #define _sentinel_ __attribute__ ((sentinel)) 56 | #define _unused_ __attribute__ ((unused)) 57 | #define _printf_(a,b) __attribute__ ((format (printf, a, b))) 58 | 59 | #define USEC_PER_SEC 1000000ULL 60 | #define MSEC_PER_SEC 1000ULL 61 | #define NSEC_PER_USEC 1000ULL 62 | 63 | #define MAX(a,b) \ 64 | ({ \ 65 | __typeof__ (a) _a = (a); \ 66 | __typeof__ (b) _b = (b); \ 67 | _a > _b ? _a : _b; \ 68 | }) 69 | 70 | /* Assert with Side Effects */ 71 | #ifdef NDEBUG 72 | #define assert_se(x) (x) 73 | #else 74 | #define assert_se(x) assert(x) 75 | #endif 76 | 77 | #ifdef __cplusplus 78 | } 79 | #endif 80 | 81 | -------------------------------------------------------------------------------- /cmake/Utils.cmake: -------------------------------------------------------------------------------- 1 | include(CheckCCompilerFlag) 2 | include(CheckCXXCompilerFlag) 3 | 4 | function(check_compilers_unknown) 5 | if (NOT CMAKE_CXX_COMPILER) 6 | message(FATAL_ERROR "The C++ compiler was not found. Please add the C++ compiler in your $PATH and re-run CMake.") 7 | endif() 8 | if (NOT CMAKE_C_COMPILER) 9 | message(FATAL_ERROR "The C compiler was not found. Please add the C++ compiler in your $PATH and re-run CMake.") 10 | endif() 11 | endfunction() 12 | 13 | function(check_git_submodules_initialized) 14 | if (NOT EXISTS "${PROJECT_SOURCE_DIR}/external/box2d/.git" OR 15 | NOT EXISTS "${PROJECT_SOURCE_DIR}/external/libpng/.git" OR 16 | NOT EXISTS "${PROJECT_SOURCE_DIR}/external/lua/.git" OR 17 | NOT EXISTS "${PROJECT_SOURCE_DIR}/external/lua-cjson/.git" OR 18 | NOT EXISTS "${PROJECT_SOURCE_DIR}/external/zlib/.git") 19 | message(FATAL_ERROR "The git submodules are not available. Please run 20 | git submodule update --init --recursive") 21 | endif() 22 | endfunction() 23 | 24 | function(add_c_flag_if_supported flags flag has) 25 | check_c_compiler_flag("${flag}" ${has}_C) 26 | if (${${has}_C}) 27 | set(${has} TRUE PARENT_SCOPE) 28 | set(${flags} "${${flags}} ${flag}" PARENT_SCOPE) 29 | endif() 30 | endfunction() 31 | 32 | function(add_cxx_flag_if_supported flags flag has) 33 | check_cxx_compiler_flag("${flag}" ${has}_CXX) 34 | if (${${has}_CXX}) 35 | set(${has} TRUE PARENT_SCOPE) 36 | set(${flags} "${${flags}} ${flag}" PARENT_SCOPE) 37 | endif() 38 | endfunction() 39 | 40 | function(add_c_cxx_flag_if_supported flags flag has) 41 | check_c_compiler_flag("${flag}" ${has}_C) 42 | if (${${has}_C}) 43 | check_cxx_compiler_flag("${flag}" ${has}_CXX) 44 | if (${${has}_CXX}) 45 | set(${has} TRUE PARENT_SCOPE) 46 | set(${flags} "${${flags}} ${flag}" PARENT_SCOPE) 47 | endif() 48 | endif() 49 | endfunction() 50 | 51 | if (CMAKE_CXX_COMPILER MATCHES ".*clang") 52 | set(CMAKE_COMPILER_IS_CLANGXX 1) 53 | endif() 54 | if (CMAKE_C_COMPILER MATCHES ".*clang") 55 | set(CMAKE_COMPILER_IS_CLANGC 1) 56 | endif() 57 | 58 | add_custom_target(astyle COMMAND 59 | astyle --indent=tab --indent-preprocessor --style=kr 60 | --pad-oper --pad-header --unpad-paren -S -n 61 | --exclude="api.hpp" --exclude="api.cpp" 62 | --exclude="api.h" --exclude="api.c" 63 | --recursive ${CMAKE_SOURCE_DIR}"/src/*.cpp" 64 | ${CMAKE_SOURCE_DIR}"/src/*.hpp" 65 | ${CMAKE_SOURCE_DIR}"/src/*.c" 66 | ${CMAKE_SOURCE_DIR}"/src/*.h" 67 | ) 68 | 69 | -------------------------------------------------------------------------------- /src/graphics/shader_bind.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option); any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "display.h" 24 | #include "shader_bind.h" 25 | #include "shader.h" 26 | #include "log.h" 27 | 28 | log_category("shader"); 29 | 30 | IMPLEMENT_PUSHPOP(Shader, shader) 31 | 32 | int mlua_new_shader(lua_State* L) 33 | { 34 | assert(L); 35 | 36 | const char *vert = NULL, *frag_color = NULL, *frag_tex = NULL; 37 | // strings can be nil 38 | if (lua_gettop(L) >= 1) { // one argument, it's the vertex shader 39 | vert = lua_tostring(L, 1); 40 | } 41 | if (lua_gettop(L) >= 2) { 42 | frag_color = lua_tostring(L, 2); 43 | } 44 | if (lua_gettop(L) >= 3) { 45 | frag_tex = lua_tostring(L, 3); 46 | } 47 | char* error; 48 | Shader* shader = display_new_shader(vert, frag_color, frag_tex, &error); 49 | if (shader) { 50 | push_shader(L, shader); 51 | return 1; 52 | } else { 53 | lua_pushnil(L); 54 | lua_pushstring(L, error); 55 | free(error); 56 | return 2; 57 | } 58 | } 59 | 60 | int mlua_use_shader(lua_State* L) 61 | { 62 | assert(L); 63 | 64 | Shader* shader = pop_shader(L, -1); 65 | display_use_shader(shader); 66 | return 0; 67 | } 68 | 69 | int mlua_use_default_shader(_unused_ lua_State* L) 70 | { 71 | display_use_default_shader(); 72 | return 0; 73 | } 74 | 75 | int mlua_feed_shader(lua_State* L) 76 | { 77 | assert(L); 78 | 79 | Shader* shader = pop_shader(L, 1); 80 | const char* name = luaL_checkstring(L, 2); 81 | lua_Number value = luaL_checknumber(L, 3); 82 | shader_feed(shader, name, value); 83 | return 0; 84 | } 85 | 86 | int mlua_free_shader(lua_State* L) 87 | { 88 | assert(L); 89 | 90 | Shader* shader = pop_shader(L, 1); 91 | display_free_shader(shader); 92 | return 0; 93 | } 94 | 95 | -------------------------------------------------------------------------------- /src/particle/particle.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | local System = drystal.System 3 | 4 | local function is_getset(funcname) 5 | if funcname:sub(1, string.len('set_min_')) == 'set_min_' then 6 | return true 7 | end 8 | return false 9 | end 10 | 11 | local funcs = {} 12 | for k, v in pairs(System) do 13 | if is_getset(k) then 14 | local attr = k:sub(string.len('get_min_') + 1) 15 | local getmin = System['get_min_' .. attr] 16 | local getmax = System['get_max_' .. attr] 17 | local setmin = System['set_min_' .. attr] 18 | local setmax = System['set_max_' .. attr] 19 | local get_both = function(data) 20 | return getmin(data), getmax(data) 21 | end 22 | local set_both = function(data, min, max) 23 | setmin(data, min) 24 | setmax(data, max or min) 25 | end 26 | funcs['set_' .. attr] = set_both 27 | funcs['get_' .. attr] = get_both 28 | end 29 | end 30 | 31 | for k, v in pairs(funcs) do 32 | System[k] = v 33 | end 34 | 35 | local function preprocess(data) 36 | local s = {} 37 | for at, value in pairs(data) do 38 | table.insert(s, {at=at, value=value}) 39 | end 40 | table.sort(s, function(a, b) return a.at < b.at end) 41 | if s[1].at ~= 0 then 42 | table.insert(s, 1, {at=0, value=s[1].value}) 43 | end 44 | if s[#s].at ~= 1 then 45 | table.insert(s, {at=1, value=s[#s].value}) 46 | end 47 | return s 48 | end 49 | 50 | function System:set_sizes(sizes) 51 | self:clear_sizes() 52 | local s = preprocess(sizes) 53 | for _, data in ipairs(s) do 54 | if type(data.value) == 'table' then 55 | self:add_size(data.at, unpack(data.value)) 56 | else 57 | self:add_size(data.at, data.value) 58 | end 59 | end 60 | end 61 | 62 | function System:set_colors(colors) 63 | self:clear_colors() 64 | local c = preprocess(colors) 65 | for _, data in ipairs(c) do 66 | local c1, c2 = data.value, data.value 67 | if type(data.value[1]) == 'table' or type(data.value[1]) == 'string' then 68 | c1 = data.value[1] 69 | c2 = data.value[2] 70 | end 71 | if type(c1) == 'string' then 72 | c1 = drystal.colors[c1] 73 | end 74 | if type(c2) == 'string' then 75 | c2 = drystal.colors[c2] 76 | end 77 | self:add_color(data.at, c1[1], c2[1], c1[2], c2[2], c1[3], c1[3]) 78 | end 79 | end 80 | 81 | function System:set_alphas(alphas) 82 | self:clear_alphas() 83 | local a = preprocess(alphas) 84 | for _, data in ipairs(a) do 85 | if type(data.value) == 'table' then 86 | self:add_alpha(data.at, unpack(data.value)) 87 | else 88 | self:add_alpha(data.at, data.value) 89 | end 90 | end 91 | end 92 | 93 | -------------------------------------------------------------------------------- /tests/graphics/camera.lua: -------------------------------------------------------------------------------- 1 | local drystal = require 'drystal' 2 | 3 | if test == nil then 4 | test = false 5 | assert(drystal.camera.x == 0) 6 | assert(drystal.camera.y == 0) 7 | assert(drystal.camera.angle == 0) 8 | assert(drystal.camera.zoom == 1) 9 | 10 | assert(drystal.camera.blo == nil) 11 | drystal.camera.blo = "t" 12 | assert(drystal.camera.blo == "t") 13 | end 14 | 15 | function drystal.init() 16 | drystal.resize(600, 400) 17 | end 18 | 19 | local angle = 0 20 | local function setupcam() 21 | drystal.camera.reset() 22 | angle = angle + 0.01 23 | drystal.camera.zoom = 0.9 24 | drystal.camera.angle = angle 25 | drystal.camera.x = 300 26 | drystal.camera.y = 200 27 | end 28 | 29 | local mx, my = 0, 0 30 | local cx, cy = 0, 0 31 | function drystal.draw() 32 | drystal.set_color(0, 0, 0) 33 | drystal.draw_background() 34 | 35 | drystal.set_color(255, 255, 255) 36 | drystal.draw_circle(300, 200, 10) 37 | 38 | drystal.camera.push() 39 | drystal.camera.reset() 40 | drystal.set_color(255, 255, 255) 41 | drystal.draw_circle(300, 200, 10) 42 | drystal.camera.pop() 43 | 44 | drystal.camera.push() 45 | setupcam() 46 | 47 | local x1, y1 = drystal.screen2scene(100, 100) 48 | local x2, y2 = drystal.screen2scene(500, 100) 49 | local x3, y3 = drystal.screen2scene(500, 300) 50 | local x4, y4 = drystal.screen2scene(100, 300) 51 | 52 | drystal.set_color 'green' 53 | drystal.draw_circle(mx, my, 13/drystal.camera.zoom) 54 | 55 | drystal.set_color 'lime' 56 | drystal.camera.pop() 57 | drystal.camera.push() 58 | drystal.camera.reset() 59 | drystal.draw_line(x1, y1, x2, y2) 60 | drystal.draw_line(x2, y2, x3, y3) 61 | drystal.draw_line(x3, y3, x4, y4) 62 | drystal.draw_line(x4, y4, x1, y1) 63 | drystal.draw_circle(x1, y1, 10) 64 | drystal.set_color 'orange' 65 | drystal.draw_circle(x2, y2, 10) 66 | drystal.set_color 'chocolate' 67 | drystal.draw_circle(x3, y3, 10) 68 | drystal.set_color 'brown' 69 | drystal.draw_circle(x4, y4, 10) 70 | drystal.camera.pop() 71 | 72 | drystal.set_color 'blue' 73 | drystal.camera.push() 74 | drystal.camera.reset() 75 | drystal.draw_circle(cx, cy, 9) 76 | drystal.camera.pop() 77 | end 78 | 79 | function drystal.mouse_motion(x, y) 80 | drystal.camera.x = 300 - x 81 | drystal.camera.y = 200 - y 82 | drystal.camera.angle = drystal.camera.angle + math.pi/32 83 | 84 | mx = x 85 | my = y 86 | 87 | drystal.camera.push() 88 | setupcam() 89 | cx, cy = drystal.screen2scene(mx, my) 90 | drystal.camera.pop() 91 | end 92 | 93 | function drystal.key_press(k) 94 | if k == 'a' then 95 | drystal.stop() 96 | end 97 | end 98 | 99 | -------------------------------------------------------------------------------- /src/util.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "macro.h" 29 | 30 | #define new(t, n) xmalloc(sizeof(t) * (n)) 31 | #define new0(t, n) xcalloc((n), sizeof(t)) 32 | #define newa(t, n) alloca(sizeof(t) * (n)) 33 | 34 | #define XREALLOC(array, nmemb, need) \ 35 | xrealloc((void **) &(array), &(nmemb), need, sizeof((array)[0]), 32) 36 | 37 | #define SWAP(a, b) { \ 38 | typeof(a) _swaptmp = (a); \ 39 | (a) = (b); \ 40 | (b) = _swaptmp; \ 41 | } 42 | 43 | #define ANSI_HIGHLIGHT_ON "\x1B[1;39m" 44 | #define ANSI_HIGHLIGHT_RED_ON "\x1B[1;31m" 45 | #define ANSI_HIGHLIGHT_YELLOW_ON "\x1B[1;33m" 46 | #define ANSI_HIGHLIGHT_BLUE_ON "\x1B[1;34m" 47 | #define ANSI_HIGHLIGHT_GRAY_ON "\x1B[1;90m" 48 | #define ANSI_HIGHLIGHT_PURPLE_ON "\x1B[1;35m" 49 | #define ANSI_HIGHLIGHT_GREEN_ON "\x1B[1;92m" 50 | #define ANSI_RESET "\x1B[0m" 51 | 52 | _malloc_ void *xmalloc(size_t size); 53 | _malloc_ void *xcalloc(size_t nmemb, size_t size); 54 | char *xstrdup(const char *s); 55 | int mkdir_p(const char *path); 56 | _sentinel_ char *strjoin(const char *s, ...); 57 | void msleep(unsigned long milisec); 58 | bool is_directory(const char *directory); 59 | bool files_are_same(const char *filea, const char *fileb); 60 | void *xrealloc(void **p, size_t *new_nmemb, size_t need, size_t size, unsigned min_nmemb); 61 | bool endswith(const char *s, const char *postfix); 62 | bool on_tty(int fd); 63 | bool stderr_use_colors(void); 64 | 65 | static inline bool startswith(const char *s, const char *prefix) 66 | { 67 | if (strncmp(s, prefix, strlen(prefix)) == 0) { 68 | return true; 69 | } 70 | 71 | return false; 72 | } 73 | 74 | static inline bool streq(const char *a, const char *b) 75 | { 76 | return strcmp(a, b) == 0; 77 | } 78 | 79 | #ifdef __cplusplus 80 | } 81 | #endif 82 | 83 | -------------------------------------------------------------------------------- /src/physics/joint_bind.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include "lua_util.h" 20 | 21 | struct lua_State; 22 | class b2Joint; 23 | 24 | struct Joint { 25 | b2Joint* joint; 26 | Joint* nextdestroy; 27 | bool getting_destroyed; 28 | int ref; 29 | }; 30 | 31 | typedef Joint RevoluteJoint; 32 | typedef Joint MouseJoint; 33 | typedef Joint DistanceJoint; 34 | typedef Joint RopeJoint; 35 | typedef Joint PrismaticJoint; 36 | typedef Joint GearJoint; 37 | typedef Joint FrictionJoint; 38 | 39 | DECLARE_PUSH(RopeJoint, rope_joint) 40 | DECLARE_PUSH(DistanceJoint, distance_joint) 41 | DECLARE_PUSH(RevoluteJoint, revolute_joint) 42 | DECLARE_PUSH(MouseJoint, mouse_joint) 43 | DECLARE_PUSH(PrismaticJoint, prismatic_joint) 44 | DECLARE_PUSH(GearJoint, gear_joint) 45 | DECLARE_PUSH(FrictionJoint, friction_joint) 46 | 47 | DECLARE_POP(Joint, joint) 48 | Joint* pop_joint_secure(lua_State* L, int index); 49 | 50 | int mlua_set_target_mouse_joint(lua_State* L); 51 | 52 | int mlua_set_length_distance_joint(lua_State* L); 53 | int mlua_set_frequency_distance_joint(lua_State* L); 54 | 55 | int mlua_set_max_length_rope_joint(lua_State* L); 56 | 57 | int mlua_set_angle_limits_revolute_joint(lua_State* L); 58 | int mlua_set_motor_speed_revolute_joint(lua_State* L); 59 | 60 | int mlua_set_enable_motor_prismatic_joint(lua_State* L); 61 | int mlua_set_motor_speed_prismatic_joint(lua_State* L); 62 | int mlua_set_enable_limit_prismatic_joint(lua_State* L); 63 | int mlua_set_max_motor_force_prismatic_joint(lua_State* L); 64 | int mlua_is_limit_enabled_prismatic_joint(lua_State* L); 65 | int mlua_is_motor_enabled_prismatic_joint(lua_State* L); 66 | 67 | int mlua_set_ratio_gear_joint(lua_State* L); 68 | int mlua_get_ratio_gear_joint(lua_State* L); 69 | 70 | int mlua_set_max_torque_friction_joint(lua_State* L); 71 | int mlua_get_max_torque_friction_joint(lua_State* L); 72 | int mlua_set_max_force_friction_joint(lua_State* L); 73 | int mlua_get_max_force_friction_joint(lua_State* L); 74 | 75 | int mlua_free_joint(lua_State* L); 76 | -------------------------------------------------------------------------------- /tests/graphics/surface_manipulations.lua: -------------------------------------------------------------------------------- 1 | local drystal = require "drystal" 2 | 3 | local spritesheet = assert(drystal.fromjson(io.open('image.json'):read('*all'))) 4 | 5 | vert = [[ 6 | attribute vec2 position; 7 | attribute vec4 color; 8 | attribute vec2 texCoord; 9 | 10 | varying vec4 fColor; 11 | varying vec2 fTexCoord; 12 | 13 | uniform vec2 destinationSize; 14 | uniform vec2 sourceSize; 15 | 16 | #define pi ]]..math.pi..[[ 17 | 18 | uniform float tick; 19 | 20 | float rand(vec2 co){ 21 | return sin(dot(co.xy, vec2(12.9898,78.233))); 22 | } 23 | 24 | void main() 25 | { 26 | vec2 pos = (2. * position/destinationSize) - 1.; 27 | pos.x += rand(vec2(pos.x, tick/10.+100.)) * .01; 28 | pos.y += rand(vec2(pos.y, tick/10.)) * .01; 29 | 30 | gl_Position = vec4(pos, 0., 1.); 31 | fColor = color; 32 | fTexCoord = texCoord / sourceSize; 33 | } 34 | ]] 35 | 36 | local x = 0 37 | local y = 0 38 | local width = 0 39 | local height = 0 40 | local shader 41 | 42 | function drystal.init() 43 | drystal.resize(600, 400) 44 | image = assert(drystal.load_surface(spritesheet.meta.image)) 45 | image:draw_from() 46 | drystal.set_alpha(0) 47 | surf = drystal.new_surface(64, 32) 48 | surf:draw_on() 49 | drystal.set_color(255, 0, 0) 50 | drystal.set_alpha(105) 51 | drystal.draw_rect(32, 0, 40, 40) 52 | 53 | drystal.set_color(200, 200, 200) 54 | drystal.set_alpha(255) 55 | local sprite = spritesheet.frames['character.png'].frame 56 | drystal.draw_sprite(sprite, 0, 0) 57 | drystal.screen:draw_on() 58 | 59 | shader = assert(drystal.new_shader(vert)) 60 | end 61 | 62 | local tick = 0 63 | function drystal.update(dt) 64 | tick = tick + dt 65 | end 66 | 67 | function drystal.draw() 68 | image:draw_from() 69 | drystal.set_alpha(255) 70 | drystal.set_color(10, 10, 30) 71 | drystal.draw_background() 72 | 73 | shader:use() 74 | shader:feed('tick', tick) 75 | drystal.set_color(255, 0, 0) 76 | drystal.set_alpha(105) 77 | drystal.draw_rect(16, 64, 40, 40) 78 | 79 | local sprite = spritesheet.frames['character.png'].frame 80 | drystal.set_color(200, 200, 200) 81 | drystal.set_alpha(255) 82 | drystal.draw_sprite_rotated(sprite, 16, 16, math.sin(tick)) 83 | drystal.use_default_shader() 84 | 85 | drystal.set_color(100, 0, 0) 86 | drystal.set_alpha(200) 87 | drystal.draw_sprite(sprite, 16+32, 16) 88 | 89 | drystal.set_color(255,255,255) 90 | drystal.set_alpha((math.sin(tick*5)/2+0.5)*255) 91 | surf:draw_from() 92 | 93 | drystal.draw_image(0, 0, 64, 32, 0, 256) 94 | end 95 | 96 | function drystal.key_press(key) 97 | if key == 'a' then 98 | drystal.stop() 99 | end 100 | end 101 | 102 | function drystal.key_release(key) 103 | end 104 | 105 | function drystal.mouse_motion(_x, _y) 106 | x = _x 107 | y = _y 108 | end 109 | 110 | -------------------------------------------------------------------------------- /src/graphics/surface.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include 20 | #include 21 | 22 | #ifndef EMSCRIPTEN 23 | #include 24 | #else 25 | #include 26 | #endif 27 | 28 | typedef struct Surface Surface; 29 | 30 | enum FilterMode { 31 | FILTER_NEAREST = GL_NEAREST, 32 | FILTER_LINEAR = GL_LINEAR, 33 | FILTER_BILINEAR = GL_LINEAR_MIPMAP_NEAREST, 34 | FILTER_TRILINEAR = GL_LINEAR_MIPMAP_LINEAR, 35 | 36 | FILTER_DEFAULT = FILTER_LINEAR, 37 | }; 38 | typedef enum FilterMode FilterMode; 39 | 40 | enum SurfaceFormat { 41 | FORMAT_LUMINANCE = GL_LUMINANCE, 42 | FORMAT_LUMINANCE_ALPHA = GL_LUMINANCE_ALPHA, 43 | FORMAT_RGB = GL_RGB, 44 | FORMAT_RGBA = GL_RGBA, 45 | }; 46 | typedef enum SurfaceFormat SurfaceFormat; 47 | 48 | struct Surface { 49 | char* filename; 50 | unsigned int w; 51 | unsigned int h; 52 | unsigned int texw; 53 | unsigned int texh; 54 | FilterMode filter; 55 | bool has_fbo; 56 | bool has_mipmap; 57 | bool npot; 58 | int ref; 59 | 60 | GLuint tex; 61 | GLuint fbo; 62 | 63 | unsigned char *pixels; 64 | bool pixels_valid; 65 | }; 66 | 67 | Surface *surface_new(unsigned int w, 68 | unsigned int h, 69 | unsigned int texw, 70 | unsigned int texh, 71 | SurfaceFormat format, 72 | void *pixels, 73 | Surface *current_from, 74 | Surface *current_on); 75 | void surface_free(Surface *s); 76 | void surface_draw_on(Surface *s); 77 | void surface_draw_from(Surface *s); 78 | void surface_set_filter(Surface *s, FilterMode filter, Surface *current_surface); 79 | void surface_get_pixel(Surface *s, unsigned int x, unsigned int y, 80 | int *red, int *green, int *blue, int *alpha, Surface *current_on); 81 | 82 | static inline void surface_get_size(const Surface *s, unsigned int *w, unsigned int *h) 83 | { 84 | assert(w); 85 | assert(h); 86 | *w = s->w; 87 | *h = s->h; 88 | } 89 | 90 | int surface_load(const char* filename, Surface **surface, Surface *current_surface); 91 | 92 | -------------------------------------------------------------------------------- /src/font/font_bind.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #include 18 | #include 19 | #include 20 | 21 | #include "font.h" 22 | #include "font_bind.h" 23 | #include "lua_util.h" 24 | 25 | IMPLEMENT_PUSHPOP(Font, font) 26 | 27 | int mlua_draw_font(lua_State* L) 28 | { 29 | assert(L); 30 | 31 | Font* font = pop_font(L, 1); 32 | const char* text = luaL_checkstring(L, 2); 33 | lua_Number x = luaL_checknumber(L, 3); 34 | lua_Number y = luaL_checknumber(L, 4); 35 | Alignment alignment = (Alignment) luaL_optinteger(L, 5, ALIGN_LEFT); 36 | font_draw(font, text, x, y, alignment); 37 | return 0; 38 | } 39 | 40 | int mlua_draw_plain_font(lua_State* L) 41 | { 42 | assert(L); 43 | 44 | Font* font = pop_font(L, 1); 45 | const char* text = luaL_checkstring(L, 2); 46 | lua_Number x = luaL_checknumber(L, 3); 47 | lua_Number y = luaL_checknumber(L, 4); 48 | font_draw_plain(font, text, x, y); 49 | return 0; 50 | } 51 | 52 | int mlua_load_font(lua_State* L) 53 | { 54 | assert(L); 55 | 56 | const char* filename = luaL_checkstring(L, 1); 57 | lua_Number size = luaL_checknumber(L, 2); 58 | Font* font = font_load(filename, size, 32, 96); 59 | if (font) { 60 | push_font(L, font); 61 | return 1; 62 | } 63 | return luaL_fileresult(L, 0, filename); 64 | } 65 | 66 | int mlua_sizeof_font(lua_State* L) 67 | { 68 | assert(L); 69 | 70 | Font* font = pop_font(L, 1); 71 | const char* text = luaL_checkstring(L, 2); 72 | lua_Number w, h; 73 | font_get_textsize(font, text, &w, &h, -1); 74 | lua_pushnumber(L, w); 75 | lua_pushnumber(L, h); 76 | return 2; 77 | } 78 | 79 | int mlua_sizeof_plain_font(lua_State* L) 80 | { 81 | assert(L); 82 | 83 | Font* font = pop_font(L, 1); 84 | const char* text = luaL_checkstring(L, 2); 85 | lua_Number w, h; 86 | font_get_textsize_plain(font, text, &w, &h); 87 | lua_pushnumber(L, w); 88 | lua_pushnumber(L, h); 89 | return 2; 90 | } 91 | 92 | int mlua_free_font(lua_State* L) 93 | { 94 | assert(L); 95 | 96 | Font* font = pop_font(L, 1); 97 | font_free(font); 98 | return 0; 99 | } 100 | 101 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.5 FATAL_ERROR) 2 | project(drystal) 3 | 4 | set(DRYSTAL_VERSION "Drystal 1.1") 5 | 6 | set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") 7 | include(Utils) 8 | include(CMakeDependentOption) 9 | 10 | check_compilers_unknown() 11 | check_git_submodules_initialized() 12 | 13 | option(BUILD_MANPAGES "Build manpages" ON) 14 | option(BUILD_ENABLE_COVERAGE "Enable code coverage" OFF) 15 | option(BUILD_PHYSICS "Enable physics module" ON) 16 | option(BUILD_WEB "Enable web module" ON) 17 | option(BUILD_AUDIO "Enable audio module" ON) 18 | option(BUILD_GRAPHICS "Enable graphics module" ON) 19 | option(BUILD_UTILS "Enable utils module" ON) 20 | 21 | cmake_dependent_option(BUILD_PARTICLE "Enable particle module (needs BUILD_GRAPHICS as dependency)" ON "BUILD_GRAPHICS" OFF) 22 | cmake_dependent_option(BUILD_STORAGE "Enable storage module (needs BUILD_UTILS as dependency)" ON "BUILD_UTILS" OFF) 23 | cmake_dependent_option(BUILD_FONT "Enable font module (needs BUILD_GRAPHICS as dependency)" ON "BUILD_GRAPHICS" OFF) 24 | cmake_dependent_option(BUILD_LIVECODING "Enable livecoding (available only on Linux)" ON "NOT EMSCRIPTEN" OFF) 25 | 26 | if(BUILD_LIVECODING AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Linux") 27 | message(FATAL_ERROR "Cannot enable BUILD_LIVECODING: Linux only") 28 | endif() 29 | 30 | if (EMSCRIPTEN) 31 | set(LINK_FLAGS "${LINK_FLAGS} -s TOTAL_MEMORY=67108864") 32 | set(LINK_FLAGS "${LINK_FLAGS} --memory-init-file 1") 33 | set(LINK_FLAGS "${LINK_FLAGS} -s NO_EXIT_RUNTIME=1") 34 | set(LINK_FLAGS "${LINK_FLAGS} -s ASM_JS=1") 35 | set(LINK_FLAGS "${LINK_FLAGS} -s ERROR_ON_UNDEFINED_SYMBOLS=1") 36 | 37 | set(LINK_FLAGS_RELEASE "${LINK_FLAGS_RELEASE} -s DISABLE_EXCEPTION_CATCHING=1") 38 | set(LINK_FLAGS_RELEASE "${LINK_FLAGS_RELEASE} -s AGGRESSIVE_VARIABLE_ELIMINATION=1") 39 | set(LINK_FLAGS_RELEASE "${LINK_FLAGS_RELEASE} -s ASSERTIONS=0") 40 | 41 | set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${LINK_FLAGS} ${LINK_FLAGS_RELEASE}") 42 | set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${LINK_FLAGS} ${LINK_FLAGS_RELEASE}") 43 | set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "${CMAKE_EXE_LINKER_FLAGS_MINSIZEREL} ${LINK_FLAGS} ${LINK_FLAGS_RELEASE}") 44 | set(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "${CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL} ${LINK_FLAGS} ${LINK_FLAGS_RELEASE}") 45 | set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} ${LINK_FLAGS} ${LINK_FLAGS_DEBUG}") 46 | set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO} ${LINK_FLAGS} ${LINK_FLAGS_DEBUG}") 47 | endif() 48 | 49 | if(BUILD_MANPAGES AND NOT EMSCRIPTEN) 50 | add_subdirectory(doc/man) 51 | endif() 52 | add_subdirectory(tools) 53 | 54 | add_subdirectory(external) 55 | add_subdirectory(src) 56 | add_subdirectory(misc/shell-completion/zsh/) 57 | -------------------------------------------------------------------------------- /src/module.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #include 24 | 25 | #define PUSH_FUNC(name, func) \ 26 | lua_pushcfunction(L, mlua_##func); \ 27 | lua_setfield(L, -2, name); 28 | 29 | #define DECLARE_MODULE(name) \ 30 | void register_##name(lua_State* L); 31 | 32 | #define BEGIN_MODULE(name) \ 33 | void register_##name(lua_State* L) { 34 | #define DECLARE_FUNCTION(name) \ 35 | lua_pushcfunction(L, mlua_##name); \ 36 | lua_setfield(L, -2, #name); 37 | #define DECLARE_BOOLEAN(name, value) \ 38 | lua_pushboolean(L, value); \ 39 | lua_setfield(L, -2, #name); 40 | #define END_MODULE() \ 41 | } 42 | 43 | #define BEGIN_CLASS(name) \ 44 | luaL_newmetatable(L, #name); \ 45 | lua_pushliteral(L, #name); \ 46 | lua_setfield(L, -2, "__type"); 47 | #define ADD_GC(func) \ 48 | PUSH_FUNC("__gc", func) 49 | #define ADD_METHOD(class, name) \ 50 | PUSH_FUNC(#name, name##_##class) 51 | #define ADD_GETSET(class, name) \ 52 | ADD_METHOD(class, get_##name) \ 53 | ADD_METHOD(class, set_##name) 54 | 55 | #define REGISTER_CLASS(name, name_in_module) \ 56 | lua_pushvalue(L, -1); \ 57 | lua_setfield(L, -2, "__index"); \ 58 | lua_setfield(L, -2, name_in_module); 59 | 60 | #define REGISTER_CLASS_WITH_INDEX(name, name_in_module) \ 61 | PUSH_FUNC("__index", name##_class_index); \ 62 | lua_setfield(L, -2, name_in_module); 63 | 64 | #define REGISTER_CLASS_WITH_INDEX_AND_NEWINDEX(name, name_in_module) \ 65 | PUSH_FUNC("__index", name##_class_index); \ 66 | PUSH_FUNC("__newindex", name##_class_newindex); \ 67 | lua_setfield(L, -2, name_in_module); 68 | 69 | #define REGISTER_MODULE(name, L) \ 70 | register_##name(L) 71 | 72 | #define DECLARE_CONSTANT_WITH_NAME(constant, constant_name) \ 73 | lua_pushnumber(L, constant); \ 74 | lua_setfield(L, -2, constant_name); 75 | 76 | #define BEGIN_ENUM() \ 77 | lua_newtable(L); 78 | #define ADD_CONSTANT(name, value) \ 79 | lua_pushnumber(L, value); \ 80 | lua_setfield(L, -2, name); 81 | #define REGISTER_ENUM(name) \ 82 | lua_setfield(L, -2, name); 83 | 84 | #define DECLARE_CONSTANT(constant) \ 85 | DECLARE_CONSTANT_WITH_NAME(constant, #constant) 86 | 87 | #ifdef __cplusplus 88 | } 89 | #endif 90 | 91 | -------------------------------------------------------------------------------- /src/graphics/buffer_bind.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option); any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #include 18 | #include 19 | #include 20 | 21 | #include "display.h" 22 | #include "buffer_bind.h" 23 | #include "log.h" 24 | 25 | log_category("buffer"); 26 | 27 | IMPLEMENT_PUSHPOP(Buffer, buffer) 28 | 29 | int mlua_new_buffer(lua_State* L) 30 | { 31 | assert(L); 32 | 33 | Buffer* buffer; 34 | if (lua_gettop(L) == 1) { 35 | lua_Integer size = luaL_checkinteger(L, 1); 36 | assert_lua_error(L, size > 0, "size should be positive"); 37 | buffer = display_new_buffer(size); 38 | } else { 39 | buffer = display_new_auto_buffer(); // let Display choose a size 40 | } 41 | assert(buffer); 42 | push_buffer(L, buffer); 43 | return 1; 44 | } 45 | 46 | int mlua_use_buffer(lua_State* L) 47 | { 48 | assert(L); 49 | 50 | Buffer* buffer = pop_buffer(L, 1); 51 | assert_lua_error(L, !buffer_was_freed(buffer), "cannot use() a freed buffer"); 52 | display_use_buffer(buffer); 53 | return 0; 54 | } 55 | 56 | int mlua_use_default_buffer(_unused_ lua_State* L) 57 | { 58 | display_use_default_buffer(); 59 | return 0; 60 | } 61 | 62 | int mlua_draw_buffer(lua_State* L) 63 | { 64 | assert(L); 65 | 66 | Buffer* buffer = pop_buffer(L, 1); 67 | lua_Number dx = 0, dy = 0; 68 | if (lua_gettop(L) >= 2) 69 | dx = luaL_checknumber(L, 2); 70 | if (lua_gettop(L) >= 3) 71 | dy = luaL_checknumber(L, 3); 72 | display_draw_buffer(buffer, dx, dy); 73 | return 0; 74 | } 75 | 76 | int mlua_reset_buffer(lua_State* L) 77 | { 78 | assert(L); 79 | 80 | Buffer* buffer = pop_buffer(L, 1); 81 | assert_lua_error(L, !buffer_was_freed(buffer), "cannot reset() a freed buffer"); 82 | buffer_reset(buffer); 83 | return 0; 84 | } 85 | 86 | int mlua_upload_and_free_buffer(lua_State* L) 87 | { 88 | assert(L); 89 | 90 | Buffer* buffer = pop_buffer(L, 1); 91 | assert_lua_error(L, !buffer_was_freed(buffer), "cannot upload_and_free() a freed buffer"); 92 | buffer_upload_and_free(buffer); 93 | display_use_default_buffer(); 94 | return 0; 95 | } 96 | 97 | int mlua_free_buffer(lua_State* L) 98 | { 99 | assert(L); 100 | 101 | Buffer* buffer = pop_buffer(L, 1); 102 | display_free_buffer(buffer); 103 | return 0; 104 | } 105 | 106 | -------------------------------------------------------------------------------- /src/graphics/camera_bind.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option); any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #include 18 | #include 19 | #include 20 | 21 | #include "display.h" 22 | #include "camera_bind.h" 23 | #include "macro.h" 24 | #include "util.h" 25 | #include "lua_util.h" 26 | 27 | int mlua_camera__newindex(lua_State* L) 28 | { 29 | assert(L); 30 | 31 | const char * name = luaL_checkstring(L, 2); 32 | if (streq(name, "x")) { 33 | lua_Number dx = luaL_checknumber(L, 3); 34 | display_set_camera_position(dx, display_get_camera()->dy); 35 | } else if (streq(name, "y")) { 36 | lua_Number dy = luaL_checknumber(L, 3); 37 | display_set_camera_position(display_get_camera()->dx, dy); 38 | } else if (streq(name, "angle")) { 39 | lua_Number angle = luaL_checknumber(L, 3); 40 | display_set_camera_angle(angle); 41 | } else if (streq(name, "zoom")) { 42 | lua_Number zoom = luaL_checknumber(L, 3); 43 | display_set_camera_zoom(zoom); 44 | } else { 45 | lua_rawset(L, 1); 46 | } 47 | 48 | return 0; 49 | } 50 | 51 | int mlua_camera__index(lua_State* L) 52 | { 53 | assert(L); 54 | 55 | const char * name = luaL_checkstring(L, 2); 56 | if (streq(name, "x")) { 57 | lua_Number dx = display_get_camera()->dx; 58 | lua_pushnumber(L, dx); 59 | return 1; 60 | } else if (streq(name, "y")) { 61 | lua_Number dy = display_get_camera()->dy; 62 | lua_pushnumber(L, dy); 63 | return 1; 64 | } else if (streq(name, "angle")) { 65 | lua_Number angle = display_get_camera()->angle; 66 | lua_pushnumber(L, angle); 67 | return 1; 68 | } else if (streq(name, "zoom")) { 69 | lua_Number zoom = display_get_camera()->zoom; 70 | lua_pushnumber(L, zoom); 71 | return 1; 72 | } 73 | return 0; 74 | } 75 | 76 | int mlua_camera_reset(_unused_ lua_State *L) 77 | { 78 | display_reset_camera(); 79 | return 0; 80 | } 81 | 82 | int mlua_camera_push(lua_State *L) 83 | { 84 | assert(L); 85 | 86 | assert_lua_error(L, !camera_stack_is_full(), "push: camera stack is full"); 87 | 88 | display_push_camera(); 89 | return 0; 90 | } 91 | 92 | int mlua_camera_pop(lua_State *L) 93 | { 94 | assert(L); 95 | 96 | assert_lua_error(L, !camera_stack_is_empty(), "push: camera stack is empty"); 97 | 98 | display_pop_camera(); 99 | return 0; 100 | } 101 | 102 | -------------------------------------------------------------------------------- /external/wavloader.c: -------------------------------------------------------------------------------- 1 | /* wavloader - public domain wav loader no warranty implied; use at your own risk 2 | * written in 2013 by kidanger 3 | * rewritten in 2014 by Ronny Chevalier 4 | */ 5 | #ifndef WAVLOADER_INCLUDE 6 | #define WAVLOADER_INCLUDE 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | #include 12 | 13 | struct wave_header { 14 | char header_id[4]; 15 | uint32_t chunk_size; 16 | char format[4]; 17 | char format_id[4]; 18 | uint32_t format_size; 19 | uint16_t audio_format; 20 | uint16_t num_channels; 21 | uint32_t sample_rate; 22 | uint32_t byte_rate; 23 | uint16_t block_align; 24 | uint16_t bits_per_sample; 25 | char data_id[4]; 26 | uint32_t data_size; 27 | }; 28 | 29 | int load_wav(const char *filename, struct wave_header *wave_header, void **audio_data); 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | #endif // WAVLOADER_INCLUDE 36 | 37 | #ifndef WAVLOADER_HEADER_ONLY 38 | #ifdef __cplusplus 39 | extern "C" { 40 | #endif 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | int load_wav(const char *filename, struct wave_header *wave_header, void **audio_data) 47 | { 48 | /* see https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ */ 49 | FILE *file; 50 | void *tmp_buffer = NULL; 51 | int ret = 0; 52 | size_t r; 53 | long filesize; 54 | 55 | if (!filename || !wave_header || !audio_data) { 56 | return -EINVAL; 57 | } 58 | 59 | file = fopen(filename, "rb"); 60 | if (!file) { 61 | return -errno; 62 | } 63 | 64 | r = fread(wave_header, sizeof(struct wave_header), 1, file); 65 | if (r != 1) { 66 | ret = -EIO; 67 | goto fail; 68 | } 69 | 70 | if (strncmp(wave_header->header_id, "RIFF", 4)) { 71 | ret = -ENOTSUP; 72 | goto fail; 73 | } 74 | if (strncmp(wave_header->format, "WAVE", 4)) { 75 | ret = -ENOTSUP; 76 | goto fail; 77 | } 78 | if (strncmp(wave_header->format_id, "fmt", 3)) { 79 | ret = -ENOTSUP; 80 | goto fail; 81 | } 82 | if (strncmp(wave_header->data_id, "data", 4)) { 83 | ret = -ENOTSUP; 84 | goto fail; 85 | } 86 | if (wave_header->format_size != 16) { 87 | ret = -ENOTSUP; 88 | goto fail; 89 | } 90 | if (wave_header->audio_format != 1) { 91 | ret = -ENOTSUP; 92 | goto fail; 93 | } 94 | 95 | fseek(file, 0L, SEEK_END); 96 | filesize = ftell(file); 97 | fseek(file, sizeof(struct wave_header), SEEK_SET); 98 | 99 | if (wave_header->data_size != filesize - sizeof(struct wave_header)) { 100 | ret = -EIO; 101 | goto fail; 102 | } 103 | 104 | tmp_buffer = malloc(wave_header->data_size); 105 | if (!tmp_buffer) { 106 | ret = -ENOMEM; 107 | goto fail; 108 | } 109 | 110 | r = fread(tmp_buffer, wave_header->data_size, 1, file); 111 | if (r != 1) { 112 | ret = -EIO; 113 | goto fail; 114 | } 115 | 116 | *audio_data = tmp_buffer; 117 | fclose(file); 118 | 119 | return ret; 120 | fail: 121 | free(tmp_buffer); 122 | fclose(file); 123 | 124 | return ret; 125 | } 126 | #ifdef __cplusplus 127 | } 128 | #endif 129 | #endif 130 | 131 | -------------------------------------------------------------------------------- /src/particle/system.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of Drystal. 3 | * 4 | * Drystal is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Drystal is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Drystal. If not, see . 16 | */ 17 | #pragma once 18 | 19 | #include // random 20 | 21 | typedef struct Color Color; 22 | typedef struct Size Size; 23 | typedef struct Alpha Alpha; 24 | typedef struct System System; 25 | 26 | #include "graphics/surface.h" 27 | #include "particle.h" 28 | 29 | #define RAND(a, b) (((float) rand()/RAND_MAX) * ((b) - (a)) + (a)) 30 | 31 | #define MAX_COLORS 16 32 | struct Color { 33 | float at; 34 | unsigned char min_r, max_r; 35 | unsigned char min_g, max_g; 36 | unsigned char min_b, max_b; 37 | }; 38 | 39 | #define MAX_SIZES 16 40 | struct Size { 41 | float at; 42 | float min, max; 43 | }; 44 | 45 | #define MAX_ALPHAS 16 46 | struct Alpha { 47 | float at; 48 | float min, max; 49 | }; 50 | 51 | struct System { 52 | Particle* particles; 53 | 54 | int cur_size; 55 | Size sizes[MAX_SIZES]; 56 | 57 | int cur_color; 58 | Color colors[MAX_COLORS]; 59 | 60 | int cur_alpha; 61 | Alpha alphas[MAX_ALPHAS]; 62 | 63 | Surface* texture; 64 | bool running; 65 | 66 | size_t size; 67 | size_t used; 68 | 69 | float x, y; 70 | float offx, offy; 71 | 72 | float min_direction, max_direction; 73 | float min_lifetime, max_lifetime; 74 | 75 | float min_initial_acceleration, max_initial_acceleration; 76 | float min_initial_velocity, max_initial_velocity; 77 | 78 | float emission_rate; 79 | float emit_counter; 80 | 81 | int sprite_x; 82 | int sprite_y; 83 | 84 | int ref; 85 | }; 86 | 87 | System *system_new(float x, float y, size_t size); 88 | System *system_clone(System* s); 89 | void system_free(System *s); 90 | 91 | void system_start(System *s); 92 | void system_stop(System *s); 93 | void system_reset(System *s); 94 | void system_draw(System *s, float dx, float dy); 95 | void system_emit(System *s); 96 | void system_update(System *s, float dt); 97 | void system_add_size(System *s, float at, float min, float max); 98 | void system_add_color(System *s, float at, unsigned char min_r, unsigned char max_r, unsigned char min_g, unsigned char max_g, unsigned char min_b, unsigned char max_b); 99 | void system_add_alpha(System *s, float at, float min, float max); 100 | void system_clear_sizes(System *s); 101 | void system_clear_colors(System *s); 102 | void system_clear_alphas(System *s); 103 | void system_set_texture(System* s, Surface* tex, float x, float y); 104 | 105 | --------------------------------------------------------------------------------