diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main.c | 198 | ||||
-rw-r--r-- | src/main.h | 23 | ||||
-rw-r--r-- | src/scene00.c | 73 | ||||
-rw-r--r-- | src/scene00.h | 12 | ||||
-rw-r--r-- | src/scene01.c | 49 | ||||
-rw-r--r-- | src/scene01.h | 12 | ||||
-rw-r--r-- | src/scene02.c | 42 | ||||
-rw-r--r-- | src/scene02.h | 12 |
8 files changed, 421 insertions, 0 deletions
diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..a73bf44 --- /dev/null +++ b/src/main.c @@ -0,0 +1,198 @@ +/* + * demoscene-eo, an ASCII art demoscene written as a gift for Emmanuel Otton retirement + * Copyright (C) 2019 Ludovic Pouzenc <ludovic@pouzenc.fr> + * + * This file is part of demoscene-eo. + * + * demoscene-eo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * demoscene-eo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with demoscene-eo. If not, see <http://www.gnu.org/licenses/> + */ +#include "main.h" +#include "scene00.h" +#include "scene01.h" +#include "scene02.h" +#define SCENE_COUNT 3 +#define SCENE_NEXT do { scene = (scene+1)%SCENE_COUNT; } while(0) + +#define EXPR_MIN_SIZE ( ge.w<80 || ge.h<25 ) +#define TEXT_MIN_SIZE "80x25" + +int main(void) +{ + int done=0, lastscene=-1, scene=0, paused=0, res; + Uint32 sdl_win_flags = SDL_WINDOW_OPENGL; + graphical_env_t ge; + scene00_env_t s00e; + scene01_env_t s01e; + scene02_env_t s02e; + + caca_event_t caca_ev; + SDL_RendererInfo renderer_info; + SDL_Event sdl_ev; + + // Initialize libcaca (http://caca.zoy.org/doxygen/libcaca/caca_8h.html) + ge.dp = caca_create_display(NULL); + if(!ge.dp) return 1; + caca_set_display_title(ge.dp, "demoscene-eo"); + caca_set_display_time(ge.dp, 16666); // 1e6µs/60 = 16666.66... It is ~60 fps + ge.cv = caca_get_canvas(ge.dp); + + ge.d = caca_create_dither(32, 256, 256, 256*4, 0x00ff0000, 0x0000ff00, 0x000000ff, 0); + if ( !ge.d ) return 2; + caca_set_dither_color(ge.d, "16"); + + // Initialize SDL (http://wiki.libsdl.org/SDL_CreateWindowAndRenderer) + // Useful snippet : https://gist.github.com/koute/7391344 + res = SDL_Init(SDL_INIT_VIDEO); + if ( res == -1) return 3; + SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); + SDL_GL_SetAttribute( SDL_GL_ACCELERATED_VISUAL, 1 ); + SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 ); + SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 ); + SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 ); + SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 ); + SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3 ); + SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 2 ); + SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE ); + + //XXX for final version, consider sdl_win_flags |= SDL_WINDOW_HIDDEN; + res = SDL_CreateWindowAndRenderer(256, 256, sdl_win_flags, &ge.sdl_win, &ge.sdl_rndr); + if ( res == -1) return 4; + SDL_SetWindowTitle(ge.sdl_win, "SDL/GL debug"); + res = SDL_GetRendererInfo(ge.sdl_rndr, &renderer_info); + if ( res < 0 ) return 5; + if ( !(renderer_info.flags & SDL_RENDERER_ACCELERATED)) return 6; + if ( !(renderer_info.flags & SDL_RENDERER_TARGETTEXTURE)) return 7; + ge.sdl_target = SDL_CreateTexture(ge.sdl_rndr, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 256, 256); + if ( ge.sdl_target == NULL ) return 9; + ge.raw_target = malloc(256*256*4); + if ( ge.raw_target == NULL ) return 10; + ge.gl_ctx = SDL_GL_CreateContext(ge.sdl_win); + if ( ge.gl_ctx == NULL ) return 11; + + + // Initialize OpenGL + glShadeModel(GL_SMOOTH); + glClearDepth(1.0f); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + + glDisable(GL_TEXTURE_2D); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glEnable(GL_CULL_FACE); + glCullFace(GL_FRONT); + glViewport(0, 0, (GLsizei)256, (GLsizei)256); + glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, 1.0f, 0.1f, 100.0f); // 1.0f==ratio + glMatrixMode(GL_MODELVIEW); glLoadIdentity(); + + // Main libcaca loop for caca window (OpenGL could be used in sceneN_next()) + ge.framecount=0; + do { + // Check canvas size at every frame because of unreliable CACA_EVENT_RESIZE + ge.w = caca_get_canvas_width(ge.cv); + ge.h = caca_get_canvas_height(ge.cv); + if ( EXPR_MIN_SIZE ) { + caca_set_color_ansi(ge.cv, CACA_BLACK, CACA_WHITE); + caca_put_str(ge.cv, 0, 0, "Need a minimum of " TEXT_MIN_SIZE " terminal"); + } else if (!paused) { + // init / free if scene transition + if ( lastscene != scene ) { + switch(lastscene) { + case 0: scene00_free(&ge, &s00e); break; + case 1: scene01_free(&ge, &s01e); break; + case 2: scene02_free(&ge, &s02e); break; + } + } + while ( lastscene != scene ) { + ge.sdl_ticks = SDL_GetTicks(); + ge.sc_framecount = 0; + switch(scene) { + case 0: res = scene00_init(&ge, &s00e); break; + case 1: res = scene01_init(&ge, &s01e); break; + case 2: res = scene02_init(&ge, &s02e); break; + } + // If scene init fail, skip to the next one + if (res) SCENE_NEXT; else lastscene = scene; + } + // Compute current scene0 frame + ge.sdl_ticks = SDL_GetTicks(); // This value wraps if the program runs for more than ~49 days + switch(scene) { + case 0: res = scene00_next(&ge, &s00e); break; + case 1: res = scene01_next(&ge, &s01e); break; + case 2: res = scene02_next(&ge, &s02e); break; + } + if (res) SCENE_NEXT; + ge.framecount++; + ge.sc_framecount++; + } + // Display it + caca_refresh_display(ge.dp); // Auto framerate limiting (see caca_set_display_time()) + + // Event handling for the libcaca "window" (depending on CACA_DRIVER env variable) + if ( caca_get_event(ge.dp, CACA_EVENT_KEY_PRESS|CACA_EVENT_RESIZE|CACA_EVENT_QUIT, &caca_ev, 0) ) { + switch(caca_get_event_type(&caca_ev)) { + case CACA_EVENT_QUIT: + done = 1; + break; + case CACA_EVENT_KEY_PRESS: + switch(caca_get_event_key_ch(&caca_ev)) { + case 'q': done = 1; break; + case 'p': paused = !paused; break; + case CACA_KEY_ESCAPE: SCENE_NEXT; break; + } + break; + /* On Debian 10, no CACA_EVENT_RESIZE when using x11 CACA_DRIVER + case CACA_EVENT_RESIZE: + w = caca_get_event_resize_width(&caca_ev); + h = caca_get_event_resize_height(&caca_ev); + small = EXPR_MIN_SIZE; + break; + */ + default: + break; + } + } + // Event handling for the SDL/GL window (debug purposes) + while(SDL_PollEvent(&sdl_ev)) { + switch(sdl_ev.type) { + case SDL_QUIT: + done = 1; + break; + case SDL_KEYDOWN: + switch(sdl_ev.key.keysym.sym) { + case SDLK_q: done = 1; break; + case SDLK_p: paused = !paused; break; + case SDLK_ESCAPE: SCENE_NEXT; break; + } + break; + default: + break; + } + } + } while(!done); + + caca_free_dither(ge.d); + caca_free_display(ge.dp); + ge.cv=NULL; + SDL_GL_DeleteContext(ge.gl_ctx); + SDL_DestroyTexture(ge.sdl_target); + SDL_DestroyRenderer(ge.sdl_rndr); + SDL_DestroyWindow(ge.sdl_win); + SDL_Quit(); + return 0; +} diff --git a/src/main.h b/src/main.h new file mode 100644 index 0000000..b2b0a6e --- /dev/null +++ b/src/main.h @@ -0,0 +1,23 @@ +#ifndef MAIN_H_INCLUDED +#define MAIN_H_INCLUDED + +#include <caca.h> +#include <SDL2/SDL.h> +#include <SDL2/SDL_opengl.h> +#include <GL/glu.h> + +typedef struct { + caca_display_t *dp; + caca_canvas_t *cv; + caca_dither_t *d; + int w, h; // caca terminal size in characters + SDL_Window* sdl_win; + SDL_Renderer *sdl_rndr; + SDL_Texture *sdl_target; + void *raw_target; + SDL_GLContext gl_ctx; + Uint32 sdl_ticks; + Uint32 framecount; + Uint32 sc_framecount; +} graphical_env_t; +#endif diff --git a/src/scene00.c b/src/scene00.c new file mode 100644 index 0000000..746db29 --- /dev/null +++ b/src/scene00.c @@ -0,0 +1,73 @@ +/* + * demoscene-eo, an ASCII art demoscene written as a gift for Emmanuel Otton retirement + * Copyright (C) 2019 XXXXXX XXXXXXX <xxxxxx@xxxxxx.fr> + * + * This file is part of demoscene-eo. + * + * demoscene-eo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * demoscene-eo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with demoscene-eo. If not, see <http://www.gnu.org/licenses/> + */ +#include "scene00.h" + +int scene00_init(graphical_env_t *ge, scene00_env_t *se) { + SDL_Surface *bmpSurf = SDL_LoadBMP("./res/eo1.bmp"); + se->eo1 = SDL_CreateTextureFromSurface(ge->sdl_rndr, bmpSurf); + SDL_FreeSurface(bmpSurf); + + return 0; +} + +void scene00_free(graphical_env_t *ge, scene00_env_t *se) { + SDL_DestroyTexture(se->eo1); se->eo1=NULL; +} + +int scene00_next(graphical_env_t *ge, scene00_env_t *se) { + // Shorthands + caca_canvas_t *cv = ge->cv; + int w = ge->w, h = ge->h; + Uint32 frame = ge->sc_framecount; + SDL_Renderer *r = ge->sdl_rndr; + // Local vars + int res; + + // https://gist.github.com/Twinklebear/8265888 + // https://forums.libsdl.org/viewtopic.php?p=51634 + + // Render all the stuff on target texture + SDL_SetRenderTarget(r, ge->sdl_target); + SDL_RenderCopy(r, se->eo1, NULL, NULL); + // [...] + + // Copy the SDL screen to SDL debug window (and display it, not mandatory) + SDL_SetRenderTarget(r, NULL); + SDL_RenderCopy(r, ge->sdl_target, NULL, NULL); + SDL_RenderPresent(r); + + // Download the rendered texture from videocard to main memory + res = SDL_RenderReadPixels(r, NULL, 0, ge->raw_target, 256*4); + + // "convert" the raw pixel stream to ASCII art on caca canevas + if ( res == 0 ) caca_dither_bitmap(cv, 0, 0, w, h, ge->d, ge->raw_target); + + // Add things on top of caca canvas + caca_set_color_ansi(cv, CACA_BLACK, CACA_WHITE); + caca_put_str(cv, (w-17)/2, h/2, "This is a message"); + caca_draw_line(cv,6,6,w-14,11, '*'); + caca_draw_thin_line(cv,frame%10,frame%10,w-10+frame%10,h-10+frame%10); + + if ( frame >= 100 ) { + return 1; + } + return 0; +} + diff --git a/src/scene00.h b/src/scene00.h new file mode 100644 index 0000000..b1c9d9d --- /dev/null +++ b/src/scene00.h @@ -0,0 +1,12 @@ +#ifndef SCENE00_H_INCLUDED +#define SCENE00_H_INCLUDED + +#include "main.h" +typedef struct { + SDL_Texture *eo1; +} scene00_env_t; + +int scene00_init(graphical_env_t *ge, scene00_env_t *se); +void scene00_free(graphical_env_t *ge, scene00_env_t *se); +int scene00_next(graphical_env_t *ge, scene00_env_t *se); +#endif diff --git a/src/scene01.c b/src/scene01.c new file mode 100644 index 0000000..2b3e9f5 --- /dev/null +++ b/src/scene01.c @@ -0,0 +1,49 @@ +/* + * demoscene-eo, an ASCII art demoscene written as a gift for Emmanuel Otton retirement + * Copyright (C) 2019 XXXXXX XXXXXXX <xxxxxx@xxxxxx.fr> + * + * This file is part of demoscene-eo. + * + * demoscene-eo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * demoscene-eo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with demoscene-eo. If not, see <http://www.gnu.org/licenses/> + */ +#include "scene01.h" + +int scene01_init(graphical_env_t *ge, scene01_env_t *se) { + return 0; +} + +void scene01_free(graphical_env_t *ge, scene01_env_t *se) { +} + +int scene01_next(graphical_env_t *ge, scene01_env_t *se) { + // Shorthands + caca_canvas_t *cv = ge->cv; + int w = ge->w, h = ge->h; + Uint32 frame = ge->sc_framecount; + + //XXX remove me + ((Uint32 *)ge->raw_target)[frame%(256*256)]=frame<<((frame%3)*8); + + caca_clear_canvas(cv); + caca_set_dither_gamma(ge->d, (100-frame%100)/100.0); + caca_dither_bitmap(cv, 0, 0, w, h, ge->d, ge->raw_target); + + caca_set_color_ansi(cv, CACA_WHITE, CACA_BLACK); + caca_put_str(cv, (w-17)/2, h/2, "This is a message"); + + if ( frame >= 300 ) { + return 1; + } + return 0; +} diff --git a/src/scene01.h b/src/scene01.h new file mode 100644 index 0000000..1f22de7 --- /dev/null +++ b/src/scene01.h @@ -0,0 +1,12 @@ +#ifndef SCENE01_H_INCLUDED +#define SCENE01_H_INCLUDED + +#include "main.h" +typedef struct { + +} scene01_env_t; + +int scene01_init(graphical_env_t *ge, scene01_env_t *se); +void scene01_free(graphical_env_t *ge, scene01_env_t *se); +int scene01_next(graphical_env_t *ge, scene01_env_t *se); +#endif diff --git a/src/scene02.c b/src/scene02.c new file mode 100644 index 0000000..1989bf0 --- /dev/null +++ b/src/scene02.c @@ -0,0 +1,42 @@ +/* + * demoscene-eo, an ASCII art demoscene written as a gift for Emmanuel Otton retirement + * Copyright (C) 2019 XXXXXX XXXXXXX <xxxxxx@xxxxxx.fr> + * + * This file is part of demoscene-eo. + * + * demoscene-eo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * demoscene-eo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with demoscene-eo. If not, see <http://www.gnu.org/licenses/> + */ +#include "scene02.h" + +int scene02_init(graphical_env_t *ge, scene02_env_t *se) { + return 0; +} + +void scene02_free(graphical_env_t *ge, scene02_env_t *se) { +} + +int scene02_next(graphical_env_t *ge, scene02_env_t *se) { + // Shorthands + caca_canvas_t *cv = ge->cv; + //int w = ge->w, h = ge->h; + Uint32 frame = ge->sc_framecount; + + caca_clear_canvas(cv); + + if ( frame >= 100 ) { + return 1; + } + return 0; +} + diff --git a/src/scene02.h b/src/scene02.h new file mode 100644 index 0000000..49abbfb --- /dev/null +++ b/src/scene02.h @@ -0,0 +1,12 @@ +#ifndef SCENE02_H_INCLUDED +#define SCENE02_H_INCLUDED + +#include "main.h" +typedef struct { + +} scene02_env_t; + +int scene02_init(graphical_env_t *ge, scene02_env_t *se); +void scene02_free(graphical_env_t *ge, scene02_env_t *se); +int scene02_next(graphical_env_t *ge, scene02_env_t *se); +#endif |