/* * sdl-scrolling - Example program for scrolling images in SDL * * Copyright (C) 2013 Antonio Ospite * * 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 . */ #include #include #include #include #include #include #include #define WIDTH 800 #define HEIGHT 480 #define FPS 30 static int mod(int a, int b) { int c = a % b; return (c < 0) ? c + b : c; } static SDL_Surface *load_image(const char *filename) { SDL_Surface *image = NULL; SDL_Surface *optimized_image = NULL; image = IMG_Load(filename); if (!image) { fprintf(stderr, "IMG_Load: %s\n", IMG_GetError()); return NULL; } optimized_image = SDL_DisplayFormat(image); if (!optimized_image) { fprintf(stderr, "erro whan calling SDL_DisplayFormat().\n"); return NULL; } SDL_FreeSurface(image); return optimized_image; } int main(int argc, char *argv[]) { int ret; SDL_Surface* screen = NULL; SDL_Surface* map = NULL; SDL_Rect viewport = {0 , 0, WIDTH, HEIGHT}; SDL_Event event; SDL_Joystick *joystick = NULL; int running = 1; Sint16 y_offset = 0; Sint16 y = 0; Sint16 lastframe_limit; Uint32 time_start; Uint32 time_end; int output_fd = -1; if (argc < 2) { fprintf(stderr, "usage: %s []\n", argv[0]); return -EINVAL; } SDL_Init(SDL_INIT_TIMER | SDL_INIT_JOYSTICK); screen = SDL_SetVideoMode(WIDTH, HEIGHT, 32, SDL_HWSURFACE); if (!screen) { fprintf(stderr, "Cannot set video mode\n"); ret = -EINVAL; goto out; } map = load_image(argv[1]); if (!map) { ret = -EINVAL; goto out; } /* Set up the output file */ if (argc >= 3) { if (strncmp(argv[2], "-", 1) == 0) { output_fd = STDOUT_FILENO; } else { output_fd = open(argv[2], O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); if (output_fd < 0) { perror("open"); ret = output_fd; goto out; } } } lastframe_limit = (map->h - HEIGHT); if (SDL_NumJoysticks() > 0) joystick = SDL_JoystickOpen(0); SDL_JoystickEventState(SDL_ENABLE); SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); while (running) { time_start = SDL_GetTicks(); while(SDL_PollEvent(&event)) { switch(event.type) { case SDL_QUIT: running = 0; break; case SDL_KEYDOWN: switch(event.key.keysym.sym) { case SDLK_ESCAPE: case SDLK_q: running = 0; break; case SDLK_UP: y_offset += 1; break; case SDLK_DOWN: y_offset -= 1; break; default: printf("key: '%s' keysym: %d\n", SDL_GetKeyName(event.key.keysym.sym), event.key.keysym.sym); break; } break; case SDL_JOYAXISMOTION: fprintf(stderr, "Joystick which: %d, axis: %d, value: %d\n", event.jaxis.which, event.jaxis.axis, event.jaxis.value); if (event.jaxis.which == 0) { if (event.jaxis.axis == 0) /* TODO: improve scaling here */ y_offset = event.jaxis.value; } break; default: /* ignore other events */ break; } } y += y_offset; y = mod(y, lastframe_limit); viewport.y = y; SDL_BlitSurface(map, &viewport, screen, NULL); SDL_Flip(screen); if (output_fd >= 0) { int len = screen->w * screen->h * screen->format->BytesPerPixel; ret = write(output_fd, screen->pixels, len); if (ret != len) { fprintf(stderr, "invalid write\n"); running = 0; } } time_end = SDL_GetTicks(); if (time_end - time_start < 1000 / FPS) SDL_Delay((1000 / FPS) - (time_end - time_start)); } ret = 0; if (output_fd >= 0) close(output_fd); if (SDL_JoystickOpened(0)) SDL_JoystickClose(joystick); SDL_FreeSurface(map); out: SDL_Quit(); return ret; }