Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR 2: examples rose, dot; make deps; more README; unused version assert #3

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ c_src/env.mk
ebin
examples/*/*.beam
priv
.DS_Store
28 changes: 28 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,37 @@
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

all:
make ebin
make bullet

ebin:
rm -rf ebin/
mkdir -p ebin/
erlc -o ebin/ src/*.erl
cd c_src && make

bullet: ebin
erlc -o examples/bullet_engine examples/bullet_engine/*.erl
cd examples/bullet_engine && ./start.sh

hello: ebin
erlc -o examples/hello_sdl examples/hello_sdl/*.erl
cd examples/hello_sdl && ./start.sh

dot: ebin
erlc -o examples/dot examples/dot/*.erl
cd examples/dot && ./start.sh

rose: ebin
erlc -o examples/rose examples/rose/*.erl
cd examples/rose && ./start.sh

clean:
@rm -f *.swp
@rm -f c_src/env.mk
@rm -f priv/esdl2.so
@rm -rf ebin/
@rm -f examples/*/*.dump
@rm -f examples/*/*.beam
@rm -f .DS_Store
@echo clean
39 changes: 35 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,50 @@
ESDL2
=====

SDL2 Erlang NIF.
SDL2 Erlang NIFs

SDL provides cross-platform low level access to graphics, audio, keyboard, mouseand joystick hardware via OpenGL and Direct3D. This is an Erlang binding to SDL2. http://www.libsdl.org/

Note: 'ESDL' used to be Erlang's graphics kit, using SDL 1, before it was replaced by wxWidgets. This is a different implementation, for a new version of SDL.

Status
------

Week-end project. Work in progress.

The following limitations apply:

Building
--------

* Erlang 17.0+ is required
* SDL 2.0.3+ is required
* SDL 2.0.3+ is required (`http://www.libsdl.org/download-2.0.php`)
* SDL\_image is required (`https://www.libsdl.org/projects/SDL_image/`)
* No support for UTF-8 strings, only Latin-1

Tip: configure SDL\_image with --disable-webp for not having to install libwebp.

Build using make:

make

Examples
--------

Samples in examples/

* Bullet Engine - rains bullets danmaku style
* Hello World - minimal visual: show a graphic
* Rose - minimal animation: draw a pixel line
* Dot - minimal animation: show a circling dot

Build and run using make from the project root.

make bullet
make hello
make rose
make dot

Ideas
-----
The following ideas need to be investigated:

* We may benefit from the reference receive optimization when doing calls
Expand Down
3 changes: 2 additions & 1 deletion c_src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ SDL2_LIBS = $(filter-out $(SDL2_LIBS_FILTER_OUT),$(shell sdl2-config --static-li

all: env.mk
mkdir -p $(PRIV_DIR)
gcc *.c -fPIC -shared -o $(PRIV_DIR)/esdl2.so -I $(ERTS_INCLUDE_DIR) \
gcc -undefined dynamic_lookup *.c -fPIC -shared \
-o $(PRIV_DIR)/esdl2.so -I $(ERTS_INCLUDE_DIR) \
`sdl2-config --cflags` $(SDL2_LIBS) -lSDL2_image

env.mk:
Expand Down
50 changes: 50 additions & 0 deletions examples/dot/dot.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
%% Minimal animation example: a single dot looping in circles.
%% Build and run from project root: make dot
%% Feel free to copy and reuse as you wish.

-module(dot).
-export([run/0]).

run() ->
spawn_opt(fun init/0, [{scheduler, 0}]).

init() ->
%% setup sdl, window and renderer
ok = sdl:start([video]),
ok = sdl:stop_on_exit(),
{ok, Window} = sdl_window:create("Dot", 10, 10, 500, 500, []),
{ok, Renderer} = sdl_renderer:create(Window, -1, [accelerated, present_vsync]),
%% start animaton
loop(#{window=>Window, renderer=>Renderer, t=>0}).

%% animation loop
loop(State) ->
events_loop(),
loop(render(State)).

%% check for termination
events_loop() ->
case sdl_events:poll() of
false -> ok;
#{type:=quit} -> terminate();
_ -> events_loop()
end.

%% render one frame
render(#{renderer:=Renderer, t:=T}=State) ->
%% clear screen
ok = sdl_renderer:set_draw_color(Renderer, 0,0,0,0),
ok = sdl_renderer:clear(Renderer),
%% draw dot
X = erlang:round(250 + 100 * math:sin(T/250) * (math:cos(T/100) + math:cos(T/10))),
Y = erlang:round(250 + 100 * math:sin(T/250) * (math:sin(T/100) + math:sin(T/10))),
ok = sdl_renderer:set_draw_color(Renderer, 255, 255, 255, 255),
ok = sdl_renderer:draw_point(Renderer, #{x=>X, y=>Y}),
%% render
ok = sdl_renderer:present(Renderer),
%% progress timeline
State#{t=>T + 1}.

terminate() ->
init:stop(),
exit(normal).
2 changes: 2 additions & 0 deletions examples/dot/start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/sh
erl +stbt db -pa ../../ebin -eval "dot:run()."
79 changes: 79 additions & 0 deletions examples/planets/planets.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
%% Minimal animation example: rose line art.
%% Build and run from project root: make rose
%% Feel free to copy and reuse as you wish.

-module(planets).
-export([run/0]).

run() ->
spawn_opt(fun init/0, [{scheduler, 0}]).

init() ->
%% setup sdl, window and renderer
ok = sdl:start([video]),
ok = sdl:stop_on_exit(),
{ok, Window} = sdl_window:create("Planets", 10, 10, 500, 500, []),
{ok, Renderer} = sdl_renderer:create(Window, -1, [accelerated, present_vsync]),
%% clear screen (once ever in this example)
ok = sdl_renderer:set_draw_color(Renderer, 0,0,0,0),
ok = sdl_renderer:clear(Renderer),
%% start animaton
loop(#{window=>Window, renderer=>Renderer, t=>os:timestamp()}).

%% animation loop
loop(State) ->
events_loop(),
render(State),
loop(State).

%% check for termination
events_loop() ->
case sdl_events:poll() of
false -> ok;
#{type:=quit} -> terminate();
_ -> events_loop()
end.

%% render one frame
render(#{renderer:=Renderer, t:=TT}=State) ->
T = timer:now_diff(os:timestamp(), TT) / 20000,
ok = sdl_renderer:set_draw_color(Renderer, 0,0,0,0),
ok = sdl_renderer:clear(Renderer),
%% draw one dot (it is not cleared next frame)
draw_star(Renderer, T),
draw_planet(Renderer, 7, 200, 450, 600, 100, T),
draw_planet(Renderer, 3, 100, 280, 300, 30, T),
draw_planet(Renderer, 3, 100, 900, 300, 30, T+70),
draw_planet(Renderer, 5, 200, 290, 200, 30, T+100),
draw_planet(Renderer, 12, 300, 650, 700, 300, T),
%% render
ok = sdl_renderer:present(Renderer).

draw_star(Renderer, T) ->
ok = sdl_renderer:set_draw_color(Renderer, 255, 255, 255, 255),
ok = sdl_renderer:draw_points(Renderer, circle(100, 250, 50, 120, T, 1)),
ok = sdl_renderer:draw_points(Renderer, circle(100, 250, 53, 30, -T, 1)),
ok = sdl_renderer:draw_points(Renderer, circle(100, 250, 45, 300, T/100, 1)).


draw_planet(Renderer, W, N, R, D, V, T) ->
X = 100 + erlang:round(R * math:cos(T/D)),
Y = 250 + erlang:round(R * math:sin(T/D) / 5),
ok = sdl_renderer:set_draw_color(Renderer, 100, 100, 100, 255),
ok = sdl_renderer:draw_points(Renderer, circle(X, Y, W, N, T/V, 1.25)),
ok = sdl_renderer:set_draw_color(Renderer, 255, 255, 255, 255),
ok = sdl_renderer:draw_points(Renderer, circle(X, Y, W, N, T/V, 1)).

%% T effects a slow ant crawl of the dashed circle line when N is small enough
%% in relation to R.
%% S gives a breathing effect of the size, scaling the entire radius.
circle(X, Y, R0, N, T, S) ->
R = S * (R0 + math:cos(T/20)), %% radius
D = math:pi() * 2 / N,
[ #{x => X + erlang:round(R * math:cos((TT+T/30)/D)),
y => Y + erlang:round(R * math:sin((TT+T/30)/D))}
|| TT <- lists:seq(1, N)].

terminate() ->
init:stop(),
exit(normal).
2 changes: 2 additions & 0 deletions examples/planets/start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/sh
erl +stbt db -pa ../../ebin -eval "planets:run()."
50 changes: 50 additions & 0 deletions examples/rose/rose.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
%% Minimal animation example: rose line art.
%% Build and run from project root: make rose
%% Feel free to copy and reuse as you wish.

-module(rose).
-export([run/0]).

run() ->
spawn_opt(fun init/0, [{scheduler, 0}]).

init() ->
%% setup sdl, window and renderer
ok = sdl:start([video]),
ok = sdl:stop_on_exit(),
{ok, Window} = sdl_window:create("Dot", 10, 10, 500, 500, []),
{ok, Renderer} = sdl_renderer:create(Window, -1, [accelerated, present_vsync]),
%% clear screen (once ever in this example)
ok = sdl_renderer:set_draw_color(Renderer, 0,0,0,0),
ok = sdl_renderer:clear(Renderer),
%% start animaton
loop(#{window=>Window, renderer=>Renderer, t=>0}).

%% animation loop
loop(State) ->
events_loop(),
loop(render(State)).

%% check for termination
events_loop() ->
case sdl_events:poll() of
false -> ok;
#{type:=quit} -> terminate();
_ -> events_loop()
end.

%% render one frame
render(#{renderer:=Renderer, t:=T}=State) ->
%% draw one dot (it is not cleared next frame)
X = erlang:round(250 + 100 * math:sin(T/250) * math:cos(T/100)),
Y = erlang:round(250 + 100 * math:sin(T/250) * math:sin(T/100)),
ok = sdl_renderer:set_draw_color(Renderer, 255, 0, 0, 255),
ok = sdl_renderer:draw_point(Renderer, #{x=>X, y=>Y}),
%% render
ok = sdl_renderer:present(Renderer),
%% progress frame number
State#{t=>T + 1}.

terminate() ->
init:stop(),
exit(normal).
2 changes: 2 additions & 0 deletions examples/rose/start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/sh
erl +stbt db -pa ../../ebin -eval "rose:run()."
6 changes: 6 additions & 0 deletions src/sdl_version.erl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

-export([get_version/0]).
-export([get_revision/0]).
-export([assert_erlang_version/0]).

-spec get_version() -> {byte(), byte(), byte()}.
get_version() ->
Expand All @@ -24,3 +25,8 @@ get_version() ->
-spec get_revision() -> string().
get_revision() ->
esdl2:get_revision().

-spec assert_erlang_version() -> true.
assert_erlang_version() ->
V = list_to_integer(string:substr(erlang:system_info(otp_release),2,2)),
true = V >= 17.