Im using codeblocks and i have install the librares already and there are no error there...
When i build the project, the compiler says it has no errors and when i run it it just pops up a windows and inside its just black, and its suppose to appear the words "Hola Mundo..." i got ariblk.ttf in the project folder...
#include <stdio.h>
#include <stdlib.h>
#include <SDL.h>
#include "SDL_ttf.h"
int main(int argc, char *argv[]) {
SDL_Color bgcolor,fgcolor;
SDL_Rect rectangulo;
SDL_Surface *screen,*ttext;
TTF_Font *fuente;
const char texto[14]="Hola Mundo...";
char msg[14];
SDL_Event event;
int done = 0;
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("No se pudo iniciar SDL: %s\n",SDL_GetError());
return 1;
}
screen = SDL_SetVideoMode(640,480,24,SDL_HWSURFACE|SDL_DOUBLEBUF);
if (screen == NULL) {
printf("No se puede inicializar el modo gráfico: %s\n",SDL_GetError());
return 1;
}
atexit(SDL_Quit);
if (TTF_Init() < 0) {
printf("No se pudo iniciar SDL_ttf: %s\n",SDL_GetError());
return 1;
}
atexit(TTF_Quit);
fuente = TTF_OpenFont("ariblk.ttf",20);
if(fuente == NULL)
{
printf("No se pudo cargar fuente %s",TTF_GetError());
}
fgcolor.r=200;
fgcolor.g=200;
fgcolor.b=10;
bgcolor.r=255;
bgcolor.g=0;
bgcolor.b=0;
sprintf(msg,"%s",texto);
ttext = TTF_RenderText_Shaded(fuente,msg,fgcolor,bgcolor);
rectangulo.y=100;
rectangulo.x=100;
rectangulo.w=ttext->w;
rectangulo.h=ttext->h;
SDL_SetColorKey(ttext,SDL_SRCCOLORKEY|SDL_RLEACCEL, SDL_MapRGB(ttext->format,255,0,0));
SDL_BlitSurface(ttext,NULL,screen,&rectangulo);
TTF_CloseFont(fuente);
SDL_FreeSurface(ttext);
while(done == 0)
{
while ( SDL_PollEvent(&event) )
{
if ( event.type == SDL_KEYDOWN )
done = 1;
}
}
return 0;
}
You need to call SDL_Flip to make your changes visible on the screen. Try adding SDL_Flip(screen); after SDL_BlitSurface in your source code.
Hope this helps!
Related
Hello there I'm beginner and learning bases of C. I'm trying to replace all ',' that users could write by some '.' for my programm can run and read it. For now when I launch it doesn't took the number after the comma.
If I write in the console whit a dot it's okay
#include <stdio.h>
#include <stdlib.h>
#include "functiun.h"
#include <string.h>
int lire(char *chaine, int longueur)
{
char *positionEntree = NULL;
// On lit le texte saisi au clavier
if (fgets(chaine, longueur, stdin) != NULL) // Pas d'erreur de saisie ?
{
positionEntree = strchr(chaine, '\n');
if (positionEntree != NULL)
{
*positionEntree = '\0';
}
return 1;
}
else
{
return 0; // On renvoie 0 s'il y a eu une erreur
}
}
double lireDouble()
{
char nombreTexte[100] = {0}; // 100 cases devraient suffire
if (lire(nombreTexte, 100))
{
// Si lecture du texte ok, convertir le nombre en double et le retourner
return strtod (nombreTexte, NULL);
}
else
{
// Si problème de lecture, renvoyer 0
return 0;
}
}
double virgulePosition (char *chaine, int longueur)
{
char *virgulePosition = NULL;
if (fgets(chaine, longueur, stdin) != NULL)
{
virgulePosition = strchr(chaine, ',');
if (virgulePosition != NULL)
{
*virgulePosition = '.';
}
}
return strtod (chaine, NULL);
}
First off all try to do not mix code which does something with the I/O functions. For example the character replace is a great candidate to be a fuunction
char *strreplace(char *haystack, char needle, char replace)
{
char *saved = haystack;
if(haystack)
{
while(*haystack)
{
if(*haystack == needle) *haystack = replace;
haystack++;
}
}
return saved;
}
I'm creating a menu in my game (available when I hit escape on the keyboard)
But the black background created with SDL_Rect and the text aren't showing and I don't understand why.
When I run my program I can change the background images by pressing on the arrows (up, down, left and right), and when I hit esc, i can't do anything until I hit esc another time, and then I can continue changing the background color with the arrows on my keyboard.
Does anybody can help me with this?
#include <SDL.h>
#include <stdio.h>
#include <stdlib.h>
#include <SDL_image.h>
#include <SDL2/SDL_ttf.h>
#define CHOICEMENU 2
void errorMessage(const char *message);
void errorMessageImg(const char *message);
void errorMessageTtf(const char *message);
int printTextTtf(SDL_Surface* window, TTF_Font* mainFont, const char* text);
int displayMenu(SDL_Surface* window, TTF_Font* font);
int main( int argc, char **argv)
{
//Pointeurs de la SDL :
SDL_Window *window = NULL;
SDL_Surface *windowSurface = NULL;
SDL_Surface *image1,*image2, *image3, *image4 = NULL;
SDL_Surface *currentImage = NULL;
SDL_Surface *icon = NULL;
SDL_Renderer *renderer = NULL;
int menu;
int running;
TTF_Init(); //initialisation des textes
TTF_Font *mainFont = NULL;
mainFont = TTF_OpenFont("couriernew.ttf",30);
icon = IMG_Load("img/flask.png");
SDL_SetWindowIcon(window,icon);
if(SDL_Init(SDL_INIT_VIDEO) != 0){ //retourne 0 si Ok
errorMessage("Erreur lors de la creation de la fenêtre et du rendu");
}
window = SDL_CreateWindow("Jeu Antoine et Robin", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN);
windowSurface = SDL_GetWindowSurface(window);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED |
SDL_RENDERER_PRESENTVSYNC);
//texture = SDL_LoadBMP("ici.bmp");
image1 = SDL_LoadBMP("img/image1.bmp");
if(image1 == NULL){
SDL_DestroyWindow(window);
errorMessage("Impossible de charger l'image 1");
}
image2 = SDL_LoadBMP("img/image2.bmp");
if(image2 == NULL){
SDL_DestroyWindow(window);
errorMessage("Impossible de charger l'image 2");
}
image3 = SDL_LoadBMP("img/image3.bmp");
if(image3 == NULL){
SDL_DestroyWindow(window);
errorMessage("Impossible de charger l'image 3");
}
image4 = SDL_LoadBMP("img/image4.bmp");
if(image4 == NULL){
SDL_DestroyWindow(window);
errorMessage("Impossible de charger l'image 4");
}
currentImage = image1;
int isRunning = 1;
SDL_Event ev;
while(isRunning == 1){
while(SDL_PollEvent(&ev) != 0 ){
if(ev.type == SDL_QUIT){
isRunning = false;
}else if(ev.type == SDL_KEYDOWN){
switch(ev.key.keysym.sym){
case SDLK_UP:
currentImage = image1;
break;
case SDLK_RIGHT:
currentImage = image2;
break;
case SDLK_LEFT:
currentImage = image3;
break;
case SDLK_DOWN:
currentImage = image4;
break;
case SDL_QUIT:
isRunning = 0;
break;
case SDLK_ESCAPE:
menu = displayMenu(windowSurface,mainFont);
if(menu == 1){
isRunning = false;
}
break;
}
}
}
SDL_BlitSurface(currentImage, NULL, windowSurface, NULL);
SDL_UpdateWindowSurface(window);
}
TTF_CloseFont(mainFont);
SDL_FreeSurface(image1);
SDL_FreeSurface(image2);
SDL_FreeSurface(image3);
SDL_FreeSurface(image4);
SDL_DestroyWindow(window);
SDL_FreeSurface(icon);
SDL_DestroyRenderer(renderer);
currentImage = image1 = image2 = image3 = NULL;
window = NULL;
SDL_Quit();
return 0;
}
int displayMenu(SDL_Surface* window, TTF_Font* font){
int x,y; // coordonées de la souris
int i;
int nMenu = CHOICEMENU; //nb de choix
const char* choice[CHOICEMENU] = {"Continuer","Quitter"};
SDL_Surface* menus[CHOICEMENU]; // surface des menus
int selected[CHOICEMENU]={0,0}; // 0 car aucun selectionné pour le moment
SDL_Color colorMenu[2]={{127,122,204},{49,100,226}};
menus[0] = TTF_RenderText_Solid(font, choice[0], colorMenu[0]);
menus[1] = TTF_RenderText_Solid(font, choice[1], colorMenu[1]);
SDL_Rect pos[CHOICEMENU];
pos[0].x = window->clip_rect.w/2 /*= centre */ - menus[0]->clip_rect.w/2;
pos[0].y = window->clip_rect.h/2 - menus[0]->clip_rect.h;
pos[1].x = window->clip_rect.w/2 - menus[0]->clip_rect.w/2;
pos[1].y = window->clip_rect.h/2 + menus[0]->clip_rect.h;
SDL_FillRect(window,&window->clip_rect,SDL_MapRGB(window-
>format,0x00,0x00,0x00));
SDL_Event ev;
while(1){
while(SDL_PollEvent(&ev)){
switch(ev.type){
case SDL_QUIT:
for(i = 0; i < CHOICEMENU ; i++){
SDL_FreeSurface(menus[i]);
}
return 1;
case SDL_MOUSEMOTION: // coordonée souris
x = ev.motion.x;
y = ev.motion.y;
for(i = 0; i < CHOICEMENU; i++){
if(x >= pos[i].x && x<= pos[i].x+pos[i].w && y>=pos[i].y &&
y<=pos[i].y+pos[i].h){
if(!selected[i]){
selected[i] = 1;
SDL_FreeSurface(menus[i]); // on suppr l'ancienne
surface
menus[i] = TTF_RenderText_Solid(font, choice[i],
colorMenu[1]);
} else {
if(selected[i]){
selected[i] = 0;
SDL_FreeSurface(menus[i]); // on suppr
l'ancienne surface
menus[i] = TTF_RenderText_Solid(font, choice[i],
colorMenu[0]);
}
}
}
case SDL_MOUSEBUTTONDOWN: //si qqn a cliquer sur la souris :
x = ev.button.x;
y = ev.button.y;
for (i = 0; i < CHOICEMENU; i+=1){
if(x >= pos[i].x && x<= pos[i].x+pos[i].w && y>=pos[i].y &&
y<=pos[i].y+pos[i].h){
for(i = 0 ;i < CHOICEMENU; i++){
SDL_FreeSurface(menus[i]);
}
return i; // On retourne la valeur actuelle : ex : si je
clique sur "continue" ça return 1
}
}
break;
case SDL_KEYDOWN:
if(ev.key.keysym.sym == SDLK_ESCAPE){
for(i = 0 ;i < CHOICEMENU; i++){
SDL_FreeSurface(menus[i]);
}
return 0;
}
}
}
for(i = 0; i < CHOICEMENU; i+=1){
SDL_BlitSurface(menus[i],NULL,window,&pos[i]);
}
}
}
}
I'm making a shell program which use execvp with a tab to execute my command.
If i put in the shell "ls -l;ls", it should exec "ls -l" (it work) then "ls" but it does "ls "
My tab will have [ls\0][-l\0], will exec perfectly
then if i try ls, my tab: [ls\0][\0] and it give me:
ls: cannot access: No such file or directory
How can I remove that last [\0] to only have [ls\0] in my tab?
Thanks
EDIT: here is the full code, can't make
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#define syserror(x) perror(errormsg[x])
#define fatalsyserror(x) syserror(x), exit(x)
#define ROUGE(m) "\033[01;31m"m"\033[0m"
#define VERT(m) "\033[01;32m"m"\033[0m"
#define FAILEDEXEC 127
#define DONTEXEC 128
#define ERR -1
#define SIZECMDLINE 4096
#define SIZE 1024
#define MAXCMD 10
#define PIPEFAILED 1
typedef struct statusProc {
int proc;
int value;
int failed;
} StatusProc;
StatusProc statusproc;
char * errormsg[] = {
"No error",
ROUGE("Impossible to fork process"),
ROUGE("Exec failed")
};
void traiterCmdInFork(char *cmd[SIZE]){
char *tab[SIZE],**ps;
int i=0;
tab[i]=cmd[i];
i++;
cmd++;
for(;*cmd && *cmd!='\0';i++,cmd++){
tab[i]=*cmd;
cmd++;
}
for (ps = tab; *ps; ps++) printf("r:%s ", *ps);
execvp(*tab, tab);
syserror(2);
exit(FAILEDEXEC);
}
int traiterInFather(char *cmd[SIZE]){
char currentdir[SIZE];
if(!strncmp(*cmd,"cd",2)){
chdir(*(cmd+1));
getcwd(currentdir, SIZE);
return 1;
} else if(!strncmp(*cmd,"status",6)){
if (!statusproc.proc){
printf("Aucune commande execute avant\n");
} else if(!statusproc.failed){
printf("%d termine avec comme code retour %d\n",statusproc.proc,statusproc.value);
} else {
printf("%d termine anormalement\n",statusproc.proc);
}
return 1;
}
return 0;
}
int main(void) {
char lgcmd[SIZECMDLINE], command[SIZE], *tabcmd[SIZE], currentdir[SIZE], *newcmd, *s, *tmp ,**ps;
pid_t p;
int i, j, nbcar, nbcmdprev, status, waitstatus, waitprev;
nbcmdprev=0;
//utiliser macro
for(;;) {
getcwd(currentdir, SIZE);
printf("%s>",currentdir);
memset(lgcmd,0,SIZECMDLINE);
fgets(lgcmd, SIZECMDLINE-1, stdin);
for(s=lgcmd; isspace(*s); s++);
s[strlen(s)-1]='\0'; //retire \n a la fin de la ligne de commande
printf("Command line:%s\n",s);
nbcar=0;
status=0;
waitprev=0;
waitstatus=0;
i=0;
newcmd=s;
printf("test");
for(;*s;s++,nbcar++){
//on avance jusqua fin dune commande
printf("R3");
if(*s==';' || *(s+1)=='\0' || *s=='|' || *s=='&'){ //traiter cas || et && et finligne
if(*s=='|' && *(s+1)=='|'){
*s++='\0';
waitprev=2;
} else if(*s=='&' && *(s+1)=='&'){
*s++='\0';
waitprev=1;
} else if(*(s+1)=='\0'){
s++;
nbcar++;
}
memset(command,0,strlen(command));
for (j = 0; j < nbcmdprev; j++) {
memset(tabcmd[j],0,strlen(tabcmd[j]));
printf("clear %d\n",j);
}
memcpy(command,newcmd,nbcar);
*s='\0';
for(tmp=command; isspace(*tmp); tmp++);
for(i=0; *tmp && tmp !=s; i++) {
tabcmd[i]=tmp;
//stopper le while quand on rencontre un ; ou & ou |
while (!isspace(*tmp) && *tmp!='\0' && *tmp!=';' && *tmp!='|' && *tmp!='&') {
printf("tmp:%c\n",*tmp);
tmp++;
}
//traiter &
if(*tmp=='|'){
waitprev=2;
*tmp++='\0';
break;
} else if(*tmp==';'){
waitprev=0;
*tmp++='\0';
break;
} else if(*tmp=='&'){
waitprev=1;
*tmp++='\0';
break;
} else if(*tmp!='\0'){
printf("tmp:%c\n",*tmp);
*tmp++='\0';
} else if(*tmp=='\0'){
printf("fin");
}
while (isspace(*tmp)) {
printf("tmp:%c\n",*tmp);
tmp++;
}
printf("tmp:%c\n",*tmp);
}
s++;
newcmd=s;
nbcar=0;
nbcmdprev=i;
if(!traiterInFather(tabcmd)){
printf("Dans if\n");
for (j = 0; j < i; j++) {
printf("len cmd%d:%d\n",j,strlen(*tabcmd));
}
p=fork();
if (p == ERR) fatalsyserror(1);
if(p) {
statusproc.proc=p;
wait(&status);
if(WIFEXITED(status)) {
if ((status=WEXITSTATUS(status)) != FAILEDEXEC) {
if(waitprev==1){
waitstatus = -1;
} else if(waitprev==2) {
waitstatus = -2;
} else {
waitstatus = 0;
}
printf(VERT("exit status of ["));
for (ps = tabcmd; *ps; ps++) printf("%s ", *ps);
printf(VERT("\b]=%d\n"), status);
//printf("\n");
statusproc.value=status;
statusproc.failed=0;
}
}
else {
statusproc.failed=1;
puts(ROUGE("Abnormal exit"));
}
} else {
printf("Command fork:");
for (ps = tabcmd; *ps; ps++) printf("-1-%s", *ps);
printf("\n" );
if((waitstatus==-1 && status==0) || (waitstatus==-2 && status!=0) ||(waitstatus==0 && status==0)){
traiterCmdInFork(tabcmd);
} else {
//stop le fils quand on ne doit pas executer commande
exit(DONTEXEC);
}
}
}
}
}
}
exit(0);
}
EDIT2: I added an int arg to traiterCmdInFork which egal the number of arg of the cmd ( ls -a = 2) so i only copy where there is text, it solved my problem.
Thanks for your help
I have been trying to write a shell in C but i keep getting e segmentation fault when running ls > test.txt (before implementing pipes it worked just fine) .
Here is the code. sorry if it is too long and not formated properly.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <fcntl.h>
#define MAX 1024
/* fonction separe donne en exercise*/
char **separe(char *chaine, const char *separateurs)
{
char **tab;
int i, s, m, size = 10;
tab = malloc(size * sizeof(char*));
m = 0;
i = 0;
while (chaine[i] != 0)
{
// saute un séparateur
for (s = 0; separateurs[s] != 0; s++)
if (chaine[i] == separateurs[s])
break;
if (separateurs[s] != 0)
{
chaine[i++] = 0; // met un fin de chaine à la place du séparateur et avance
continue; // les séparateurs n'ont pas été épuisés
}
if (chaine[i] != 0)
tab[m++] = chaine + i;
if (m == size)
{
// si j'atteinds la limite de la taille de mon tableau, je l'agrandis.
size += 10;
tab = realloc(tab, size * sizeof(char*));
}
// saute les caractères non séparateurs
for (; chaine[i] != 0; i++)
{
for (s = 0; separateurs[s] != 0; s++)
if (chaine[i] == separateurs[s])
break;
if (separateurs[s] != 0)
break; // trouvé un caractère séparateur, j'arrête d'avancer et je passe au mot suivant
}
}
tab[m] = NULL;
return(tab);
}
void decaler2gauche(char ** tab, int pos)
{
int i = pos;
while( tab[i+2] != NULL )
{
tab[i] = tab[i+2];
i++;
}
tab[i] = NULL;
}
char** pipetest( char **arg) {
int sizeTab = 0;
int k,j;
char **newtab;
for (k = 0; arg[k] != NULL; k++)
{
sizeTab++;
}
int i =0;
while( arg[i] != NULL )
{
if( strncmp(arg[i],"|",1) == 0 )
{
for (j=0;j < i ; j++){
newtab[i] = arg[i];
}
break;
}
i++;
}
newtab[i] = NULL;
return newtab;
}
char** pipetest2( char **arg) {
int sizeTab = 0;
int k , j;
char **newtab;
for (k = 0; arg[k] != NULL; k++)
{
sizeTab++;
}
int i =0;
while( arg[i] != NULL )
{
if( strncmp(arg[i],"|",1) == 0 )
{
for ( j= i+1 ; j < sizeTab ; j++ ) {
newtab[j] = arg[j];
}
break;
}
i++;
}
newtab[sizeTab] = NULL;
return newtab;
}
/* la fonction main*/
int main(int argc, char *argv[]) {
char cmd[MAX];
char **commande; //ici on met la commande
char *newcommande[MAX]; // ici on met la commande apres avoir verifie le contenu de commande
int i, j, k,t,a, fd, fd2, raison ; // les variables utilise
char *tmp, *new_path , *new_path1 , *new_path2;
char *ge_path, *path, **tab;
int test;
int status , status2; // la variable test pour le access
char **commande1;
char **commande2;
pid_t pid , pid2;
// récupère la valeur de $PATH
ge_path = getenv("PATH");
// crée une copie locale modifiable
// (on ne doit pas modifier la zone mémoire renvoyée par getenv)
path = malloc(strlen(ge_path) + 1);
strcpy(path, ge_path);
tab = separe(path, ":");
while (1) {
int copy = 0;
int paste = 0;
int piping = 0;
int fdout;
int fdin;
int tabfd[2];
printf("myshell > ");
fgets(cmd, MAX, stdin);
commande = separe(cmd, " \n");
/* Cette boucle verifie si la commande passe en parametre est dans le PAth ou pas*/
for (i = 0; tab[i] != NULL; i++)
{
char tmp[MAX];
sprintf(tmp, "%s/%s", tab[i], commande[0]);
if ((test = access(tmp, X_OK)) == 0)
{
new_path = tmp;
break;
}
}
char* fileNameIn;
char* fileNameOut;
for (j = 0; commande[j] != NULL; j++)
{
if (strcmp(commande[j], ">") == 0) //out
{
fileNameOut = commande[j + 1];
fdout = open(fileNameOut, O_CREAT | O_WRONLY | O_TRUNC, 0666);
if (fdout == -1)
{
perror("open\n");
exit(1);
}
decaler2gauche(commande,j);
copy = 1;
}
if (strcmp(commande[j], "<") == 0) //in
{
fileNameIn = commande[j + 1];
printf("%s\n", fileNameIn);
fdin = open(fileNameIn, O_RDONLY);
if (fdin == -1)
{
perror("open\n");
exit(1);
}
paste = 1;
decaler2gauche(commande,j);
}
if (strcmp(commande[j], "|") == 0) // pipe {
{
piping = 1;
}
newcommande[j] = commande[j];
}
if (piping) {
commande1=pipetest(newcommande);
commande2=pipetest2(newcommande);
for (i = 0; tab[i] != NULL; i++)
{
char tmp[MAX];
sprintf(tmp, "%s/%s", tab[i], commande1[0]);
if ((test = access(tmp, X_OK)) == 0)
{
new_path1 = tmp;
break;
}
}
for (i = 0; tab[i] != NULL; i++)
{
char tmp[MAX];
sprintf(tmp, "%s/%s", tab[i], commande2[0]);
if ((test = access(tmp, X_OK)) == 0)
{
new_path2 = tmp;
break;
}
}
pipe(tabfd);
switch (pid=fork()) {
case -1: // le cas d erreur
perror("fork");
exit(1);
case 0:// le fils
close(1);
dup(tabfd[1]);
if (paste)
{
if (dup2(fdin, 0) == -1)
{
perror("dup2 fdin \n");
exit(1);
}
}
if (copy)
{
if (dup2(fdout, 1) == -1)
{
perror("dup2 fdin \n");
exit(1);
}
}
execv(new_path1, commande1);
perror("cmd");
exit(1);
default :
wait(&status2);
break;
}
switch (pid2=fork()) {
case -1: // le cas d erreur
perror("fork");
exit(1);
case 0:// le fils
close(0);
dup(tabfd[0]);
if (paste)
{
if (dup2(fdin, 0) == -1)
{
perror("dup2 fdin \n");
exit(1);
}
}
if (copy)
{
if (dup2(fdout, 1) == -1)
{
perror("dup2 fdin \n");
exit(1);
}
}
execv(new_path2, commande2);
perror("cmd");
exit(1);
default :
wait(&status);
break;
}
close(tabfd[0]);
close(tabfd[1]);
}
else {
switch (pid = fork())
{
case -1: // le cas d erreur
perror("fork");
exit(1);
case 0:// le fils
if (paste)
{
if (dup2(fdin, STDIN_FILENO) == -1)
{
perror("dup2 fdin \n");
exit(1);
};
}
if (copy)
{
if (dup2(fdout, STDOUT_FILENO) == -1)
{
perror("dup2 fdin \n");
exit(1);
};
}
execv(new_path, commande);
perror("cmd");
exit(1);
default:
wait(&status);
break ;
}
}
free(commande);
free(tmp);
}
free(tab);
//free(commande);
free(path);
free(new_path);
exit(0);
}
What is the best way to code a game loop in Allegro 5 that always runs at the same speed, and that properly separates drawing logic from update logic? Should I use threads or not? Should I make use of the new Allegro event system?
Taken from the allegro wiki:
al_install_timer(1.0 / FPS);
...
while (1) {
al_wait_for_event(queue, &event);
/* handle input events */
if (event.type == ALLEGRO_EVENT_TIMER) {
handle_game_tick();
need_redraw = true;
}
if (need_redraw && al_event_queue_is_empty(queue)) {
render_last_frame();
need_redraw = false;
}
}
If you want frame skipping, skip the render_last_frame() command whenever you detect that you are lagging behind in frames (e.g. by using the al_current_time() function).
Here is a more complete version of Allefant's answer (follow the link for detailed line-by-line explanation):
#include <stdio.h>
#include <allegro5/allegro.h>
const float FPS = 60;
int main(int argc, char **argv)
{
ALLEGRO_DISPLAY *display = NULL;
ALLEGRO_EVENT_QUEUE *event_queue = NULL;
ALLEGRO_TIMER *timer = NULL;
bool redraw = true;
if(!al_init()) {
fprintf(stderr, "failed to initialize allegro!\n");
return -1;
}
timer = al_create_timer(1.0 / FPS);
if(!timer) {
fprintf(stderr, "failed to create timer!\n");
return -1;
}
display = al_create_display(640, 480);
if(!display) {
fprintf(stderr, "failed to create display!\n");
al_destroy_timer(timer);
return -1;
}
event_queue = al_create_event_queue();
if(!event_queue) {
fprintf(stderr, "failed to create event_queue!\n");
al_destroy_display(display);
al_destroy_timer(timer);
return -1;
}
al_register_event_source(event_queue, al_get_display_event_source(display));
al_register_event_source(event_queue, al_get_timer_event_source(timer));
al_clear_to_color(al_map_rgb(0,0,0));
al_flip_display();
al_start_timer(timer);
while(1)
{
ALLEGRO_EVENT ev;
al_wait_for_event(event_queue, &ev);
if(ev.type == ALLEGRO_EVENT_TIMER) {
redraw = true;
}
else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
break;
}
if(redraw && al_event_queue_is_empty(event_queue)) {
redraw = false;
al_clear_to_color(al_map_rgb(0,0,0));
al_flip_display();
}
}
al_destroy_timer(timer);
al_destroy_display(display);
al_destroy_event_queue(event_queue);
return 0;
}