aboutsummaryrefslogtreecommitdiff
path: root/vendor/hare-sdl2/cmd/demo
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--vendor/hare-sdl2/cmd/demo/main.ha199
1 files changed, 199 insertions, 0 deletions
diff --git a/vendor/hare-sdl2/cmd/demo/main.ha b/vendor/hare-sdl2/cmd/demo/main.ha
new file mode 100644
index 0000000..3ba1b1c
--- /dev/null
+++ b/vendor/hare-sdl2/cmd/demo/main.ha
@@ -0,0 +1,199 @@
+use fmt;
+use fs;
+use sdl2;
+use sdl2::{ SDL_GameControllerAxis, SDL_EventType, SDL_RendererFlags, SDL_WindowFlags };
+use sdl2::image;
+use sdl2::mixer;
+use strings;
+
+type object = struct {
+ tex: *sdl2::SDL_Texture,
+ w: int, h: int,
+ x: int, y: int,
+ dx: int, dy: int,
+};
+
+type state = struct {
+ quit: bool,
+ window: *sdl2::SDL_Window,
+ render: *sdl2::SDL_Renderer,
+ nbutton: int,
+ hare: object,
+ cat: object,
+};
+
+export fn main() void = {
+ match (run()) {
+ case let err: sdl2::error =>
+ fmt::fatal("SDL2 error:", sdl2::strerror(err));
+ case let err: fs::error =>
+ fmt::fatal("Error:", fs::strerror(err));
+ case void => void;
+ };
+};
+
+fn run() (void | fs::error | sdl2::error) = {
+ sdl2::SDL_Init(sdl2::SDL_INIT_VIDEO
+ | sdl2::SDL_INIT_AUDIO
+ | sdl2::SDL_INIT_GAMECONTROLLER)!;
+ defer sdl2::SDL_Quit();
+ image::IMG_Init(image::IMG_InitFlags::PNG | image::IMG_InitFlags::JPG)!;
+ defer image::IMG_Quit();
+
+ mixer::Mix_Init(mixer::MIX_InitFlags::OGG)!;
+ defer mixer::Mix_Quit();
+ mixer::Mix_OpenAudio(mixer::MIX_DEFAULT_FREQUENCY, mixer::MIX_DEFAULT_FORMAT,
+ mixer::MIX_DEFAULT_CHANNELS, 1024)!;
+ defer mixer::Mix_CloseAudio();
+
+ const win = sdl2::SDL_CreateWindow("Hare SDL2 demo",
+ sdl2::SDL_WINDOWPOS_UNDEFINED, sdl2::SDL_WINDOWPOS_UNDEFINED,
+ 640, 480, SDL_WindowFlags::NONE)?;
+ defer sdl2::SDL_DestroyWindow(win);
+
+ const render = sdl2::SDL_CreateRenderer(win, -1, SDL_RendererFlags::NONE)?;
+ defer sdl2::SDL_DestroyRenderer(render);
+
+ let controller: nullable *sdl2::SDL_GameController = null;
+ for (let i = 0; i < sdl2::SDL_NumJoysticks()?; i += 1) {
+ if (!sdl2::SDL_IsGameController(i)) {
+ continue;
+ };
+ match (sdl2::SDL_GameControllerOpen(i)) {
+ case let c: *sdl2::SDL_GameController =>
+ controller = c;
+ sdl2::SDL_GameControllerRumble(c, 0x4000, 0x4000, 1000): void;
+ break;
+ case sdl2::error => void;
+ };
+ };
+ defer match (controller) {
+ case null => void;
+ case let c: *sdl2::SDL_GameController =>
+ sdl2::SDL_GameControllerClose(c);
+ };
+
+ let sample = mixer::load_file("sample.ogg")?;
+ defer mixer::Mix_FreeChunk(sample);
+ mixer::Mix_PlayChannelTimed(0, sample, -1)?;
+
+ let state = state {
+ window = win,
+ render = render,
+ hare = load_object(render, "mascot.jpg")?,
+ cat = load_object(render, "cat.png")?,
+ ...
+ };
+ defer sdl2::SDL_DestroyTexture(state.hare.tex);
+ defer sdl2::SDL_DestroyTexture(state.cat.tex);
+
+ state.hare.dx = 2;
+ state.hare.dy = 2;
+
+ for (!state.quit) {
+ update(&state)?;
+ draw(&state)?;
+ sdl2::SDL_Delay(1000 / 60);
+ };
+};
+
+fn update(state: *state) (void | sdl2::error) = {
+ let ev = sdl2::event { ... };
+ for (sdl2::SDL_PollEvent(&ev)? == 1) switch (ev.event_type) {
+ case SDL_EventType::QUIT =>
+ state.quit = true;
+ return;
+ case SDL_EventType::CONTROLLERAXISMOTION =>
+ let delta = ev.caxis.value: int * 10 / sdl2::SDL_JOYSTICK_AXIS_MAX;
+ if (axis_x(ev.caxis.axis)) {
+ state.cat.dx = delta;
+ };
+ if (axis_y(ev.caxis.axis)) {
+ state.cat.dy = delta;
+ };
+ case SDL_EventType::CONTROLLERBUTTONDOWN =>
+ state.nbutton += 1;
+ case SDL_EventType::CONTROLLERBUTTONUP =>
+ state.nbutton -= 1;
+ case => void;
+ };
+
+ let width = 0, height = 0;
+ sdl2::SDL_GetWindowSize(state.window, &width, &height);
+
+ state.hare.x += state.hare.dx;
+ state.hare.y += state.hare.dy;
+ if (state.hare.x <= 0 || state.hare.x + state.hare.w >= width) {
+ state.hare.dx = -state.hare.dx;
+ };
+ if (state.hare.y <= 0 || state.hare.y + state.hare.h >= height) {
+ state.hare.dy = -state.hare.dy;
+ };
+
+ state.cat.x += state.cat.dx;
+ state.cat.y += state.cat.dy;
+ if (state.cat.x <= 0) {
+ state.cat.x = 0;
+ };
+ if (state.cat.x > width - state.cat.w) {
+ state.cat.x = width - state.cat.w;
+ };
+ if (state.cat.y <= 0) {
+ state.cat.y = 0;
+ };
+ if (state.cat.y > height - state.cat.h) {
+ state.cat.y = height - state.cat.h;
+ };
+};
+
+fn draw(state: *state) (void | sdl2::error) = {
+ if (state.nbutton == 0) {
+ sdl2::SDL_SetRenderDrawColor(state.render, 50, 50, 50, 255)?;
+ } else {
+ sdl2::SDL_SetRenderDrawColor(state.render, 50, 50, 200, 255)?;
+ };
+ sdl2::SDL_RenderClear(state.render)?;
+
+ draw_object(state, &state.hare)?;
+ draw_object(state, &state.cat)?;
+ sdl2::SDL_RenderPresent(state.render);
+};
+
+fn draw_object(state: *state, obj: *object) (void | sdl2::error) = {
+ sdl2::SDL_RenderCopy(state.render, obj.tex, null, &sdl2::SDL_Rect {
+ x = obj.x,
+ y = obj.y,
+ w = obj.w,
+ h = obj.h,
+ })?;
+};
+
+fn axis_x(axis: SDL_GameControllerAxis) bool = {
+ switch (axis) {
+ case SDL_GameControllerAxis::LEFTX, SDL_GameControllerAxis::RIGHTX =>
+ return true;
+ case =>
+ return false;
+ };
+};
+
+fn axis_y(axis: SDL_GameControllerAxis) bool = {
+ switch (axis) {
+ case SDL_GameControllerAxis::LEFTY, SDL_GameControllerAxis::RIGHTY =>
+ return true;
+ case =>
+ return false;
+ };
+};
+
+fn load_object(render: *sdl2::SDL_Renderer, path: str) (object | sdl2::error) = {
+ const tex = image::IMG_LoadTexture(render, path)?;
+ let w = 0, h = 0;
+ sdl2::SDL_QueryTexture(tex, null, null, &w, &h)?;
+ return object {
+ tex = tex,
+ w = w,
+ h = h,
+ ...
+ };
+};