Added load, play and stop sound functions

Author Mitja Felicijan <mitja.felicijan@gmail.com> 2025-08-11 12:21:24 +0200
Committer Mitja Felicijan <mitja.felicijan@gmail.com> 2025-08-11 12:21:24 +0200
Commit fa1aa7793bbe2a3647435798c56f43945278bcd0 (patch)
-rw-r--r-- README.md 22
-rw-r--r-- main.c 98
-rw-r--r-- tests/sounds/effect1.wav bin 0 B -> 25.6 KB
-rw-r--r-- tests/sounds/song1.ogg bin 0 B -> 100.9 KB
-rw-r--r-- tests/test.lua 23
5 files changed, 126 insertions, 17 deletions
diff --git a/README.md b/README.md
...
27
set_fps(60)
27
set_fps(60)
28
  
28
  
29
axe_image = load_image("images/axe.png")
29
axe_image = load_image("images/axe.png")
  
30
slash_effect = load_sound("sounds/slash.wav")
30
  
31
  
31
while window_running() do
32
while window_running() do
32
    start_drawing()
33
    start_drawing()
...
43
  
44
  
44
	if button_down(button.PAD_UP) then
45
	if button_down(button.PAD_UP) then
45
		draw_text("Pad Up", 10, 10, 20, color.VIOLET)
46
		draw_text("Pad Up", 10, 10, 20, color.VIOLET)
  
47
	end
  
48
  
  
49
	if button_pressed(button.A) then
  
50
        play_sound(slash_effect)
46
	end
51
	end
47
  
52
  
48
    draw_image(axe_image, 100, 200)
53
    draw_image(axe_image, 100, 200)
...
80
| `draw_circle`    | `number center_x`, `number center_y`, `number radius`, `color color`                        |          |
85
| `draw_circle`    | `number center_x`, `number center_y`, `number radius`, `color color`                        |          |
81
| `draw_ellipse`   | `number center_x`, `number center_y`, `number radius_h`, `number radius_v`, `color color`   |          |
86
| `draw_ellipse`   | `number center_x`, `number center_y`, `number radius_h`, `number radius_v`, `color color`   |          |
82
| `draw_triangle`  | `number x1`, `number y1`, `number x2`, `number y2`, `number x3`, `number y3`, `color color` |          |
87
| `draw_triangle`  | `number x1`, `number y1`, `number x2`, `number y2`, `number x3`, `number y3`, `color color` |          |
83
| `load_image`     | `string filepath`                                                                           | `string` |
88
| `load_image`     | `string filepath`                                                                           | `uid`    |
84
| `draw_image`     | `string uid`, `number x`, `number y`                                                        |          |
89
| `draw_image`     | `uid uid`, `number x`, `number y`                                                           |          |
85
| `load_audio`     | `TODO`                                                                                      |          |
  
86
| `button_down`    | `button button`                                                                             | `bool`   |
90
| `button_down`    | `button button`                                                                             | `bool`   |
87
| `button_pressed` | `button button`                                                                             | `bool`   |
91
| `button_pressed` | `button button`                                                                             | `bool`   |
  
92
| `load_sound`     | `string filepath`                                                                           | `uid`    |
  
93
| `play_sound`     | `uid uid`                                                                                   |          |
  
94
| `stop_sound`     | `uid uid`                                                                                   |          |
88
  
95
  
89
### Controller mappings
96
### Controller mappings
90
  
97
  
...
138
- https://github.com/raysan5/raylib
145
- https://github.com/raysan5/raylib
139
- https://github.com/rxi/json.lua
146
- https://github.com/rxi/json.lua
140
- https://dejavu-fonts.github.io/
147
- https://dejavu-fonts.github.io/
  
148
- https://freetestdata.com/audio-files/
141
  
149
  
142
## Cool tools
150
## Cool tools
143
  
151
  
144
- https://hardwaretester.com/gamepad
152
- Controller testing:
145
- https://www.raylib.com/examples/core/loader.html?name=core_input_gamepad
153
    - https://hardwaretester.com/gamepad
  
154
    - https://www.raylib.com/examples/core/loader.html?name=core_input_gamepad
  
155
- Sound effect generators:
  
156
    - https://www.bfxr.net
  
157
    - https://sfxr.me
146
  
158
  
147
## Interesting games
159
## Interesting games
148
  
160
  
...
diff --git a/main.c b/main.c
...
19
#define VERSION "x.x"
19
#define VERSION "x.x"
20
#define DEBUG_LEVEL LOG_DEBUG
20
#define DEBUG_LEVEL LOG_DEBUG
21
#define FONT_IMPORT_SIZE 30
21
#define FONT_IMPORT_SIZE 30
22
#define UID_LENGTH 36
22
#define UID_LENGTH 64
23
#define GAMEPAD_INDEX 0
23
#define GAMEPAD_INDEX 0
24
#define XBOX_ALIAS_1 "xbox"
24
#define XBOX_ALIAS_1 "xbox"
25
#define XBOX_ALIAS_2 "x-box"
25
#define XBOX_ALIAS_2 "x-box"
...
37
	int count;
37
	int count;
38
} ImageList;
38
} ImageList;
39
  
39
  
  
40
typedef struct ExternalSound {
  
41
	char uid[UID_LENGTH + 1];
  
42
	Sound sound;
  
43
	struct ExternalSound *next;
  
44
} ExternalSound;
  
45
  
  
46
typedef struct {
  
47
	ExternalSound *head;
  
48
	ExternalSound *tail;
  
49
	int count;
  
50
} SoundList;
  
51
  
40
typedef struct {
52
typedef struct {
41
	Font font;
53
	Font font;
42
	int font_size;
54
	int font_size;
43
	Camera2D camera;
55
	Camera2D camera;
44
	ImageList images;
56
	ImageList images;
  
57
	SoundList sounds;
45
} Context;
58
} Context;
46
  
59
  
47
// Setting up global context.
60
// Setting up global context.
...
59
}
72
}
60
  
73
  
61
void init_image_list(ImageList *list) {
74
void init_image_list(ImageList *list) {
  
75
	list->head = NULL;
  
76
	list->tail = NULL;
  
77
	list->count = 0;
  
78
}
  
79
  
  
80
void init_sound_list(SoundList *list) {
62
	list->head = NULL;
81
	list->head = NULL;
63
	list->tail = NULL;
82
	list->tail = NULL;
64
	list->count = 0;
83
	list->count = 0;
...
106
	ctx.camera.offset = (Vector2){ GetScreenHeight()/2.0f, GetScreenHeight()/2.0f };
125
	ctx.camera.offset = (Vector2){ GetScreenHeight()/2.0f, GetScreenHeight()/2.0f };
107
	ctx.camera.rotation = 0.0f;
126
	ctx.camera.rotation = 0.0f;
108
	ctx.camera.zoom = 1.0f;
127
	ctx.camera.zoom = 1.0f;
  
128
  
  
129
	InitAudioDevice();
109
  
130
  
110
	return 0;
131
	return 0;
111
}
132
}
...
423
	}
444
	}
424
	ctx.images.count++;
445
	ctx.images.count++;
425
  
446
  
426
	TraceLog(LOG_WARNING, "[adding]\t %s (%d)", img->uid, strlen(img->uid));
447
	TraceLog(LOG_WARNING, "[add_img] %s (%d)", img->uid, strlen(img->uid));
427
  
448
  
428
	lua_pushstring(L, img->uid);
449
	lua_pushstring(L, img->uid);
429
	return 1;
450
	return 1;
430
}
451
}
431
  
452
  
432
static int l_load_audio(lua_State *L) {
  
433
	return 0;
  
434
}
  
435
  
  
436
static int l_draw_image(lua_State *L) {
453
static int l_draw_image(lua_State *L) {
437
	const char *uid = luaL_checkstring(L, 1);
454
	const char *uid = luaL_checkstring(L, 1);
438
	int x = luaL_checknumber(L, 2);
455
	int x = luaL_checknumber(L, 2);
...
441
	ExternalImage *current = ctx.images.head;
458
	ExternalImage *current = ctx.images.head;
442
	while (current) {
459
	while (current) {
443
		if (strncmp(current->uid, uid, UID_LENGTH) == 0) {
460
		if (strncmp(current->uid, uid, UID_LENGTH) == 0) {
444
			/* TraceLog(LOG_WARNING, "[match]\t %s (%d)", uid, strlen(uid)); */
  
445
			DrawTexture(current->texture, x, y, WHITE);
461
			DrawTexture(current->texture, x, y, WHITE);
446
			break;
462
			break;
447
		}
463
		}
...
451
	return 0;
467
	return 0;
452
}
468
}
453
  
469
  
  
470
static int l_load_sound(lua_State *L) {
  
471
	const char *filepath = luaL_checkstring(L, 1);
  
472
  
  
473
	ExternalSound *snd = malloc(sizeof(ExternalSound));
  
474
	if (!snd) {
  
475
		TraceLog(LOG_FATAL, "Out of memory!");
  
476
		return 0;
  
477
	}
  
478
  
  
479
	snd->sound = LoadSound(filepath);
  
480
	generate_uid(snd->uid, UID_LENGTH);
  
481
	snd->next = NULL;
  
482
  
  
483
	if (ctx.sounds.tail) {
  
484
		ctx.sounds.tail->next = snd;
  
485
		ctx.sounds.tail = snd;
  
486
	} else {
  
487
		ctx.sounds.head = snd;
  
488
		ctx.sounds.tail = snd;
  
489
	}
  
490
	ctx.sounds.count++;
  
491
  
  
492
	TraceLog(LOG_WARNING, "[add_snd] %s (%d)", snd->uid, strlen(snd->uid));
  
493
  
  
494
	lua_pushstring(L, snd->uid);
  
495
	return 1;
  
496
}
  
497
  
  
498
static int l_play_sound(lua_State *L) {
  
499
	const char *uid = luaL_checkstring(L, 1);
  
500
  
  
501
	ExternalSound *current = ctx.sounds.head;
  
502
	while (current) {
  
503
		if (strncmp(current->uid, uid, UID_LENGTH) == 0) {
  
504
			PlaySound(current->sound);
  
505
			break;
  
506
		}
  
507
		current = current->next;
  
508
	}
  
509
  
  
510
	return 0;
  
511
}
  
512
  
  
513
static int l_stop_sound(lua_State *L) {
  
514
	const char *uid = luaL_checkstring(L, 1);
  
515
  
  
516
	ExternalSound *current = ctx.sounds.head;
  
517
	while (current) {
  
518
		if (strncmp(current->uid, uid, UID_LENGTH) == 0) {
  
519
			StopSound(current->sound);
  
520
			break;
  
521
		}
  
522
		current = current->next;
  
523
	}
  
524
  
  
525
	return 0;
  
526
}
  
527
  
454
static void help(const char *argv0) {
528
static void help(const char *argv0) {
455
	printf("Usage: %s [options]\n"
529
	printf("Usage: %s [options]\n"
456
			"\nAvailable options:\n"
530
			"\nAvailable options:\n"
...
469
int main(int argc, char *argv[]) {
543
int main(int argc, char *argv[]) {
470
	srand(time(NULL));
544
	srand(time(NULL));
471
	init_image_list(&ctx.images);
545
	init_image_list(&ctx.images);
  
546
	init_sound_list(&ctx.sounds);
472
  
547
  
473
	TraceLogLevel debug_level = LOG_WARNING;
548
	TraceLogLevel debug_level = LOG_WARNING;
474
	const char *run_file = NULL;
549
	const char *run_file = NULL;
...
537
		lua_register(L, "get_width", l_get_width);
612
		lua_register(L, "get_width", l_get_width);
538
		lua_register(L, "get_height", l_get_height);
613
		lua_register(L, "get_height", l_get_height);
539
  
614
  
540
		lua_register(L, "load_image", l_load_image);
  
541
		lua_register(L, "load_audio", l_load_audio);
  
542
  
  
543
		lua_register(L, "button_down", l_button_down);
615
		lua_register(L, "button_down", l_button_down);
544
		lua_register(L, "button_pressed", l_button_pressed);
616
		lua_register(L, "button_pressed", l_button_pressed);
545
  
617
  
...
551
		lua_register(L, "draw_circle", l_draw_circle);
623
		lua_register(L, "draw_circle", l_draw_circle);
552
		lua_register(L, "draw_ellipse", l_draw_ellipse);
624
		lua_register(L, "draw_ellipse", l_draw_ellipse);
553
		lua_register(L, "draw_triangle", l_draw_triangle);
625
		lua_register(L, "draw_triangle", l_draw_triangle);
  
626
		
  
627
		lua_register(L, "load_image", l_load_image);
554
		lua_register(L, "draw_image", l_draw_image);
628
		lua_register(L, "draw_image", l_draw_image);
  
629
  
  
630
		lua_register(L, "load_sound", l_load_sound);
  
631
		lua_register(L, "play_sound", l_play_sound);
  
632
		lua_register(L, "stop_sound", l_play_sound);
555
  
633
  
556
		// Interpreting and running input file Lua script.
634
		// Interpreting and running input file Lua script.
557
		if (luaL_loadfile(L, run_file) || lua_pcall(L, 0, 0, 0)) {
635
		if (luaL_loadfile(L, run_file) || lua_pcall(L, 0, 0, 0)) {
...
diff --git a/tests/sounds/effect1.wav b/tests/sounds/effect1.wav
diff --git a/tests/sounds/song1.ogg b/tests/sounds/song1.ogg
diff --git a/tests/test.lua b/tests/test.lua
...
10
test_camera_speed = 200
10
test_camera_speed = 200
11
test_images_asset1 = load_image("tests/icons/icon_1.png")
11
test_images_asset1 = load_image("tests/icons/icon_1.png")
12
test_images_asset2 = load_image("tests/icons/icon_2.png")
12
test_images_asset2 = load_image("tests/icons/icon_2.png")
  
13
test_sounds_sound1 = load_sound("tests/sounds/effect1.wav")
  
14
test_sounds_sound2 = load_sound("tests/sounds/song1.ogg")
  
15
test_sounds_volume = 100
13
  
16
  
14
function test_api()
17
function test_api()
15
	draw_rect(100, 100, 300, 200, color.YELLOW)
18
	draw_rect(100, 100, 300, 200, color.YELLOW)
...
140
end
143
end
141
  
144
  
142
function test_images()
145
function test_images()
143
	draw_text(string.format("uid: %s", test_images_asset1), 50, 50, 20, color.VIOLET)
146
	draw_text(string.format("uid: %s", test_images_asset1), 30, 30, 20, color.VIOLET)
144
	draw_text(string.format("uid: %s", test_images_asset2), 50, 80, 20, color.VIOLET)
147
	draw_text(string.format("uid: %s", test_images_asset2), 30, 55, 20, color.VIOLET)
145
  
148
  
146
	draw_image(test_images_asset1, 150, 150)
149
	draw_image(test_images_asset1, 150, 150)
147
	draw_image(test_images_asset2, 200, 200)
150
	draw_image(test_images_asset2, 200, 200)
148
end
151
end
149
  
152
  
  
153
function test_sounds()
  
154
	draw_text("Press button A to play a short sound effect.", 30, 30, 20, color.BLUE)
  
155
	draw_text("Press button B to play a longer sound effect.", 30, 55, 20, color.BLUE)
  
156
  
  
157
	if button_pressed(button.A) then
  
158
		draw_text("Button A pressed", 30, 85, 20, color.YELLOW)
  
159
		play_sound(test_sounds_sound1)
  
160
	end
  
161
  
  
162
	if button_pressed(button.B) then
  
163
		draw_text("Button B pressed", 30, 85, 20, color.YELLOW)
  
164
		play_sound(test_sounds_sound2)
  
165
	end
  
166
end
  
167
  
150
while window_running() do
168
while window_running() do
151
	start_drawing()
169
	start_drawing()
152
	clear_window(color.BLACK)
170
	clear_window(color.BLACK)
...
156
	-- test_buttons()
174
	-- test_buttons()
157
	-- test_camera()
175
	-- test_camera()
158
	-- test_images()
176
	-- test_images()
  
177
	-- test_sounds()
159
  
178
  
160
	draw_info()
179
	draw_info()
161
	stop_drawing()
180
	stop_drawing()
...