From 8391427d10e9f774316fc864d120fc02f08128ba Mon Sep 17 00:00:00 2001 From: Pat Thoyts Date: Tue, 15 Jun 2010 22:03:19 +0100 Subject: [PATCH] lowcpu: reduce the cpu usage by the gameloop. This patch adds support for building using nmake and MSVC on windows and also modifies the gameloop to drop the cpu usage significantly using a timer and waiting rather than constantly polling the SDL loop. Signed-off-by: Pat Thoyts --- Makefile.vc | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/ag.c | 79 +++++++++++++++++++------------ src/ag.rc | 38 +++++++++++++++ src/dlb.c | 4 +- src/linked.c | 2 +- src/sprite.c | 18 ++++++++ src/sprite.h | 1 + 7 files changed, 237 insertions(+), 33 deletions(-) create mode 100644 Makefile.vc create mode 100644 src/ag.rc diff --git a/Makefile.vc b/Makefile.vc new file mode 100644 index 0000000..5e2a0c1 --- /dev/null +++ b/Makefile.vc @@ -0,0 +1,128 @@ +# -*- Makefile -*- +# +# +# Copyright (C) 2006 Pat Thoyts +# +#------------------------------------------------------------------------- +# $Id$ +#------------------------------------------------------------------------- + +VERSION=0.2 + +# You should set SDLDIR to the directory containing your SDL include +# and lib directories. +!ifndef SDLDIR +SDLDIR =/opt +!endif + +#------------------------------------------------------------------------- +# There should be no need to edit below this point. +#------------------------------------------------------------------------- + +SRCDIR =src + +!ifndef DEBUG +DEBUG =0 +!endif +!ifndef PROFILE +PROFILE =0 +!endif +!ifndef SYMBOLS +SYMBOLS = 0 +!endif +!ifndef CC +CC=cl +!endif +!ifndef LINK +LINK=link +!endif + +!if $(DEBUG) +OUTDIR =Debug +CFLAGS =-Od -Zi -GZ -MDd -D_DEBUG +LDFLAGS=-debug:full -debugtype:cv +!else +OUTDIR =Release +!if $(SYMBOLS) +CFLAGS =-Od -Zi -Op -Gs -MD -DNDEBUG +LDFLAGS=-debug -opt:ref -opt:icf,3 +!else +CFLAGS =-O2 -Otip -Gs -MD -DNDEBUG +LDFLAGS=-release -opt:ref -opt:icf,3 +!endif +!endif + +!if $(PROFILE) +CFLAGS =$(CFLAGS) -Zi +LDFLAGS=$(LDFLAGS) -profile -map +!endif + +!if "$(OS)" == "Windows_NT" +RMDIR = rmdir /s /q >NUL +!else +RMDIR = deltree /y +!endif +DEL = del /f /q + +TMPDIR =$(OUTDIR)\Objects + +CC =$(CC) -nologo +LD =$(LINK) -nologo + +CFLAGS =$(CFLAGS) -W3 -YX -Fp$(TMPDIR)^\ +INC =-I$(SDLDIR)/include +DEFS =-DWIN32 -DHAVE_OPENGL -Dmain=SDL_main +LIBS =-libpath:$(SDLDIR)/lib SDLmain.lib SDL.lib SDL_mixer.lib kernel32.lib +LDFLAGS=$(LDFLAGS) -subsystem:windows + +OBJS = \ + $(TMPDIR)\ag.obj \ + $(TMPDIR)\dlb.obj \ + $(TMPDIR)\linked.obj \ + $(TMPDIR)\sprite.obj \ + $(TMPDIR)\ag.res + +all: ag +ag: setup $(OUTDIR)\ag.exe + +$(OUTDIR)\ag.exe: $(OBJS) + $(LD) $(LDFLAGS) -out:$@ $** $(LIBS) + +.PHONY: all ag + +#------------------------------------------------------------------------- +setup: + @if not exist $(OUTDIR) mkdir $(OUTDIR) + @if not exist $(TMPDIR) mkdir $(TMPDIR) + +clean: + @if exist $(TMPDIR)\NUL $(RMDIR) $(TMPDIR) >NUL + +realclean: clean + @if exist $(OUTDIR)\NUL $(RMDIR) $(OUTDIR) >NUL + +.PHONY: setup clean realclean +#------------------------------------------------------------------------- + +.SUFFIXES:.c .cpp .rc + +{$(SRCDIR)}.c{$(TMPDIR)}.obj:: + $(CC) $(CFLAGS) $(DEFS) $(INC) -Fo$(TMPDIR)\ -c @<< +$< +<< + +{$(SRCDIR)}.cpp{$(TMPDIR)}.obj:: + $(CC) $(CFLAGS) $(DEFS) $(INC) -Fo$(TMPDIR)\ -c @<< +$< +<< + +{$(SRCDIR)}.rc{$(TMPDIR)}.res: + $(RC) -fo $@ -r -D__WIN32__ \ + -DCOMMAVERSION=$(VERSION:.=,),0,0 \ + -DVERSION=\"$(VERSION)\" \ +!if $(DEBUG) + -d DEBUG \ +!endif + $< + +#------------------------------------------------------------------------- diff --git a/src/ag.c b/src/ag.c index 0e2ca8e..c2c13be 100755 --- a/src/ag.c +++ b/src/ag.c @@ -67,6 +67,10 @@ version who changes #include "sprite.h" #include "ag.h" +#ifdef _MSC_VER +#define snprintf _snprintf +#endif + //module level variables for game control char shuffle[] = "£££££££"; char answer[] = "£££££££"; @@ -341,7 +345,7 @@ void ag(struct node** head, struct dlb_node* dlbHead, char** guess, char** remai char* newGuess; char* newRemain; -int totalLen=0, guessLen=0, remainLen=0, i; +int totalLen=0, guessLen=0, remainLen=0; // allocate space for our working variables guessLen = strlen(*guess); @@ -365,6 +369,7 @@ int totalLen=0, guessLen=0, remainLen=0, i; } if (strlen(newRemain)){ + size_t i; ag(&(*head), dlbHead, &newGuess, &newRemain); for (i=totalLen-1;i>0;i--){ @@ -867,7 +872,7 @@ void updateScore(SDL_Surface* screen){ // we'll display the total Score, this is the game score char buffer [256]; -int i; +size_t i; SDL_Rect fromrect, torect, blankRect; blankRect.x = SCORE_WIDTH * 11; @@ -1176,8 +1181,8 @@ int numSwaps; while(thisLetter != NULL){ if (thisLetter->box == SHUFFLE){ - thisLetter->toX = (whereinstr(shufflePos, thisLetter->index+1) * (GAME_LETTER_WIDTH + GAME_LETTER_SPACE)) + BOX_START_X; - thisLetter->index = whereinstr(shufflePos, thisLetter->index+1); + thisLetter->toX = (whereinstr(shufflePos, (char)(thisLetter->index+1)) * (GAME_LETTER_WIDTH + GAME_LETTER_SPACE)) + BOX_START_X; + thisLetter->index = whereinstr(shufflePos, (char)(thisLetter->index+1)); } thisLetter = thisLetter->next; @@ -1487,7 +1492,7 @@ int i; // show background ShowBMP("images/background.bmp",screen, 0,0); - destroyLetters(&(*letters)); + destroyLetters(letters); guess = malloc(sizeof(char)*50); remain = malloc(sizeof(char)*50); @@ -1552,8 +1557,17 @@ int i; } - - +static Uint32 +TimerCallback(Uint32 interval, void *param) +{ + SDL_UserEvent evt; + evt.type = SDL_USEREVENT; + evt.code = 0; + evt.data1 = 0; + evt.data2 = 0; + SDL_PushEvent((SDL_Event *)&evt); + return 0; +} /*********************************************************** synopsis: a big while loop that runs the full length of the @@ -1591,7 +1605,10 @@ void gameLoop(struct node** head, struct dlb_node* dlbHead, SDL_Surface* screen, int done=0; SDL_Event event; int timeNow; +SDL_TimerID timer; +int timer_delay = 20; + timer = SDL_AddTimer(timer_delay, TimerCallback, NULL); // main game loop while (!done){ @@ -1669,13 +1686,11 @@ int timeNow; //displayLetters(screen); shuffleRemaining = 0; - - } if (clearGuess){ // clear the guess; - if (clearWord(&(*letters)) > 0) + if (clearWord(letters) > 0) Mix_PlayChannel(-1, getSound("clear"),0); clearGuess = 0; @@ -1685,22 +1700,25 @@ int timeNow; done=1; } - while (SDL_PollEvent(&event)) + while (SDL_WaitEvent(&event)) { - switch (event.type) { - case SDL_MOUSEBUTTONDOWN: - clickDetect(event.button.button, event.button.x, event.button.y, screen, *head, &(*letters)); - break; - - case SDL_KEYUP: - handleKeyboardEvent(&event, *head, &(*letters)); - break; - case SDL_QUIT: - done=1; + if (event.type == SDL_USEREVENT) { + timer_delay = anySpritesMoving(letters) ? 10 : 100; + moveSprites(&screen, letters, letterSpeed); + timer = SDL_AddTimer(timer_delay, TimerCallback, NULL); + break; + } else if (event.type == SDL_MOUSEBUTTONDOWN) { + clickDetect(event.button.button, event.button.x, + event.button.y, screen, *head, letters); + } else if (event.type == SDL_KEYUP) { + handleKeyboardEvent(&event, *head, letters); + } else if (event.type == SDL_QUIT) { + done = 1; + break; } - } - moveSprites(&screen, &(*letters), letterSpeed); + moveSprites(&screen, letters, letterSpeed); } + } } @@ -1724,10 +1742,17 @@ SDL_Surface *screen; struct sprite* letters = NULL; //pthread_t audio; + // buffer sounds + int audio_rate = MIX_DEFAULT_FREQUENCY; + Uint16 audio_format = AUDIO_S16; + int audio_channels = 1; + int audio_buffers = 256; + + // seed the random generator srand(time(NULL)); - if (SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO) < 0){ + if (SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO|SDL_INIT_TIMER) < 0){ fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError()); exit(1); } @@ -1743,12 +1768,6 @@ struct sprite* letters = NULL; SDL_WM_SetCaption("Anagramarama", "ANAGRAMARAMA"); - // buffer sounds - int audio_rate = MIX_DEFAULT_FREQUENCY; - Uint16 audio_format = AUDIO_S16; - int audio_channels = 1; - int audio_buffers = 256; - if(Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_buffers)){ printf("unable to open audio!\n"); exit(1); diff --git a/src/ag.rc b/src/ag.rc new file mode 100644 index 0000000..8563d59 --- /dev/null +++ b/src/ag.rc @@ -0,0 +1,38 @@ +// ag.rc - +// +// There is no need to modify this file. +// + +#include + +VS_VERSION_INFO VERSIONINFO + FILEVERSION COMMAVERSION + PRODUCTVERSION COMMAVERSION + FILEFLAGSMASK 0x3fL +#ifdef DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "Anagramarama " VERSION "\0" + VALUE "OriginalFilename", "ag" VERSION ".exe\0" + VALUE "CompanyName", "GPL\0" + VALUE "FileVersion", VERSION "\0" + VALUE "LegalCopyright", "Copyright \251 2003 Colm Gallagher\0" + VALUE "ProductName", "Anagramarama " VERSION "\0" + VALUE "ProductVersion", VERSION "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/src/dlb.c b/src/dlb.c index 029aacf..3277378 100755 --- a/src/dlb.c +++ b/src/dlb.c @@ -45,7 +45,7 @@ void dlb_push(struct dlb_node** dlbHead, char* thisWord){ // add a new word to the dictionary struct dlb_node* current = *dlbHead; struct dlb_node* previous = NULL; -int i=0; +size_t i=0; char letter; int child = 0; int sibling = 0; @@ -119,7 +119,7 @@ int dlb_lookup(struct dlb_node* dlbHead, char* thisWord){ struct dlb_node* current = dlbHead; struct dlb_node* previous = NULL; -int i=0; +size_t i=0; char letter; int retval = 0; diff --git a/src/linked.c b/src/linked.c index 3bb0204..45fd8d2 100755 --- a/src/linked.c +++ b/src/linked.c @@ -155,7 +155,7 @@ int duplicate = 0; if (!duplicate){ len = strlen(anagram+1); - newNode->anagram = malloc(sizeof(char)*len); + newNode->anagram = malloc(sizeof(char)*(len + 1)); strcpy(newNode->anagram, anagram); newNode->length = len + 1; newNode->found = 0; diff --git a/src/sprite.c b/src/sprite.c index 051703a..39c40fc 100755 --- a/src/sprite.c +++ b/src/sprite.c @@ -69,6 +69,24 @@ SDL_Rect rect; SDL_BlitSurface((*movie)->replace, NULL, *screen, &rect); } +/********************************************************************/ +static int +isSpriteMoving(struct sprite *p) +{ + /* returns true if this sprite needs to move */ + return (p->y != p->toY) || (p->x != p->toX); +} +int +anySpritesMoving(struct sprite **letters) +{ + struct sprite *current; + for (current = *letters; current != NULL; current = current->next) { + if (isSpriteMoving(current)) + return 1; + } + return 0; +} + /********************************************************************/ void moveSprite(SDL_Surface** screen, struct sprite** movie, int letterSpeed){ diff --git a/src/sprite.h b/src/sprite.h index c54c2c1..14aefbe 100755 --- a/src/sprite.h +++ b/src/sprite.h @@ -49,3 +49,4 @@ int nextBlankPosition(int box, int* index); //void clickDetect(int button, int x, int y, SDL_Surface *screen, struct sprite** letters); void destroyLetters(struct sprite** letters); //void buildLetters(struct sprite** letters, SDL_Surface* screen); +int anySpritesMoving(struct sprite **letters); -- 2.23.0