Skip to content

Instantly share code, notes, and snippets.

@DeclanHoare
Last active August 5, 2017 06:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DeclanHoare/2ba4b3462a40d60074c54c3617476102 to your computer and use it in GitHub Desktop.
Save DeclanHoare/2ba4b3462a40d60074c54c3617476102 to your computer and use it in GitHub Desktop.
AROOO SDL
/*
Copyright 2017 Declan Hoare
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <bsd/stdlib.h>
#include <ftw.h>
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_mixer.h>
#include <SDL_ttf.h>
/* PLEASE SET THIS TO THE PATH TO A BADA$$ TTF YOU HAVE INSTALLED */
const char ttfpath[] = "/usr/share/fonts/TTF/trebuc.ttf";
/* SET THIS TO YOUR B.A.M. BACKGROUNDS STASH (SUPPORTS PNG & JPG) */
const char bgdir[] = "bg";
/* SET THIS TO YOUR MUSIC DIRECTORY (NULL FOR NO SOUND) */
const char* musicdir = "music";
/* OTHER SETTINGS YOU CAN TWEAK FOR A PERSONALISED AROOOO */
const int w = 800, h = 600;
#define numlines 14
#define linesize 34
const int fontsize = 36;
const int tickfrequency = 20;
const int bgchangefrequency = 30000;
const SDL_Color textcolour = {127, 0, 0};
TTF_Font* font;
SDL_Surface* textlines[numlines];
char text[linesize];
int idx = 0; /* CURRENT LINE NUMBER */
bool lineanim = false; /* SCREEN IS FULL AND SCROLLING */
double animoffset = 0;
int animoffset_rounded = 0;
int ticktimer = 0;
bool quit = false;
SDL_Event ev;
SDL_Surface* surf;
SDL_Window* window;
Mix_Music* music_stream = NULL;
int numtracks = 0;
char** tracks = NULL;
int numbgs = 0;
char** bgs = NULL;
int lastbg_offset_x, lastbg_offset_y, currbg_offset_x, currbg_offset_y;
SDL_Surface* lastbg = NULL;
SDL_Surface* currbg = NULL;
int bgopacity = 255;
int bgtimer = 0;
int total = 0, delta;
void lower_str(char* str)
{
for (char* ptr = str; *ptr; ptr++)
*ptr = tolower(*ptr);
}
int add_background(const char* fpath, const struct stat* sb, int typeflag)
{
char* ext = strrchr(fpath, '.');
if (ext)
{
ext = strdup(ext + 1);
lower_str(ext);
if ((strcmp(ext, "png") == 0) || (strcmp(ext, "jpg") == 0) || (strcmp(ext, "jpeg") == 0))
{
numbgs++;
bgs = realloc(bgs, numbgs * sizeof(char*));
bgs[numbgs - 1] = strdup(fpath);
}
free(ext);
}
return 0;
}
int add_track(const char* fpath, const struct stat* sb, int typeflag)
{
char* ext = strrchr(fpath, '.');
if (ext)
{
ext = strdup(ext + 1);
lower_str(ext);
if ((strcmp(ext, "mp3") == 0) || (strcmp(ext, "ogg") == 0) || (strcmp(ext, "wav") == 0))
{
numtracks++;
tracks = realloc(tracks, numtracks * sizeof(char*));
tracks[numtracks - 1] = strdup(fpath);
}
free(ext);
}
return 0;
}
void next_track(void)
{
if (music_stream)
Mix_FreeMusic(music_stream);
music_stream = Mix_LoadMUS(tracks[arc4random_uniform(numtracks)]);
Mix_PlayMusic(music_stream, 1);
}
void next_background(void)
{
if (lastbg != currbg)
SDL_FreeSurface(lastbg);
lastbg = currbg;
lastbg_offset_x = currbg_offset_x;
lastbg_offset_y = currbg_offset_y;
SDL_Surface* unscaled = IMG_Load(bgs[arc4random_uniform(numbgs)]);
int neww, newh;
if (unscaled->w > unscaled->h)
{
neww = w;
newh = (int)round(((double) unscaled->h / unscaled->w) * neww);
currbg_offset_x = 0;
currbg_offset_y = (int)round(((double) h / 2) - ((double) newh / 2));
}
else
{
newh = h;
neww = (int)round(((double) unscaled->w / unscaled->h) * newh);
currbg_offset_y = 0;
currbg_offset_x = (int)round(((double) w / 2) - ((double) neww / 2));
}
currbg = SDL_CreateRGBSurfaceWithFormat(0, neww, newh, 32, SDL_PIXELFORMAT_RGBA32);
SDL_BlitScaled(unscaled, NULL, currbg, NULL);
SDL_FreeSurface(unscaled);
}
void cleanup(void)
{
if (musicdir)
Mix_FreeMusic(music_stream);
for (int i = 0; i < numtracks; i++)
free(tracks[i]);
free(tracks);
for (int i = 0; i < numbgs; i++)
free(bgs[i]);
free(bgs);
TTF_CloseFont(font);
SDL_FreeSurface(surf);
SDL_DestroyWindow(window);
if (musicdir)
Mix_Quit();
IMG_Quit();
TTF_Quit();
SDL_Quit();
}
int main(int argc, char** argv)
{
arc4random_stir();
unsigned flags = SDL_INIT_VIDEO;
if (musicdir)
flags |= SDL_INIT_AUDIO;
SDL_Init(flags);
TTF_Init();
IMG_Init(IMG_INIT_PNG | IMG_INIT_JPG);
if (musicdir)
Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048);
window = SDL_CreateWindow("AROOO SDL", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w, h, SDL_WINDOW_SHOWN);
surf = SDL_GetWindowSurface(window);
font = TTF_OpenFont(ttfpath, fontsize);
ftw(bgdir, add_background, 2);
if (numbgs)
next_background();
if (musicdir)
ftw(musicdir, add_track, 2);
if (numtracks)
next_track();
atexit(cleanup);
memset(text, 0, linesize);
memcpy(text, "AR", 2);
int bgcolour = SDL_MapRGBA(surf->format, 0, 0, 0, 255);
while (!quit)
{
SDL_FillRect(surf, NULL, bgcolour);
delta = SDL_GetTicks() - total;
total += delta;
if (lineanim)
{
animoffset += (double) delta / tickfrequency;
if (animoffset >= textlines[0]->h)
{
if (textlines[0] != textlines[1])
SDL_FreeSurface(textlines[0]);
memmove(textlines, textlines + 1, (numlines - 1) * sizeof(SDL_Surface*));
textlines[numlines - 1] = NULL;
animoffset = 0;
lineanim = false;
}
animoffset_rounded = (int)round(animoffset);
}
if (!lineanim)
{
ticktimer += delta;
while (ticktimer >= tickfrequency)
{
ticktimer -= tickfrequency;
int len = strlen(text);
if (len < linesize - 1)
text[len] = 'O';
else
{
idx++;
memset(text, 0, linesize);
}
if (idx < numlines)
{
if (textlines[idx])
SDL_FreeSurface(textlines[idx]);
textlines[idx] = text[0] ? TTF_RenderText_Blended(font, text, textcolour) : NULL;
}
else
{
idx = numlines - 1;
lineanim = true;
}
}
}
if (numtracks && !Mix_PlayingMusic())
next_track();
SDL_Rect dest;
dest.w = dest.h = 0;
if (numbgs)
{
bgtimer += delta;
if (bgtimer >= bgchangefrequency)
{
bgtimer %= bgchangefrequency;
next_background();
bgopacity = 0;
}
}
if (bgopacity < 255 && lastbg != currbg)
{
bgopacity += delta;
if (bgopacity > 255)
bgopacity = 255;
SDL_SetSurfaceAlphaMod(currbg, bgopacity);
SDL_SetSurfaceBlendMode(currbg, SDL_BLENDMODE_BLEND);
SDL_SetSurfaceAlphaMod(lastbg, 255 - bgopacity);
SDL_SetSurfaceBlendMode(lastbg, SDL_BLENDMODE_BLEND);
dest.x = lastbg_offset_x;
dest.y = lastbg_offset_y;
SDL_BlitSurface(lastbg, NULL, surf, &dest);
}
dest.x = currbg_offset_x;
dest.y = currbg_offset_y;
SDL_BlitSurface(currbg, NULL, surf, &dest);
dest.x = 0;
dest.y = -animoffset_rounded;
for (int i = 0; textlines[i] && i <= idx; i++)
{
if (textlines[i])
SDL_BlitSurface(textlines[i], NULL, surf, &dest);
dest.y = textlines[i]->h * (i + 1) - animoffset_rounded;
}
SDL_UpdateWindowSurface(window);
while (SDL_PollEvent(&ev) != 0)
if (ev.type == SDL_QUIT)
quit = true;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment