diff --git a/.vscode/settings.json b/.vscode/settings.json index 5d84152..dfb5941 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,6 +7,7 @@ "array": "c", "string": "c", "string_view": "c", - "shape.h": "c" + "shape.h": "c", + "xfixes.h": "c" } } \ No newline at end of file diff --git a/build.sh b/build.sh index ee0dd38..06d5562 100755 --- a/build.sh +++ b/build.sh @@ -5,4 +5,5 @@ echo gcc src/main.c -o res/main $(pkg-config --cflags --libs sdl3 x11 xfixes sdl gcc src/main.c src/neko.c -I src/ -o res/main $(pkg-config --cflags --libs sdl3 x11 xfixes sdl3-image) -lm echo Running... -DISPLAY=:1 ./res/main +#DISPLAY=:1 ./res/main +./res/main diff --git a/res/main b/res/main index 059b97b..141aa85 100755 Binary files a/res/main and b/res/main differ diff --git a/res/oneko.gif b/res/oneko.gif new file mode 100644 index 0000000..a009c2c Binary files /dev/null and b/res/oneko.gif differ diff --git a/res/real_oneko.gif b/res/real_oneko.gif new file mode 100644 index 0000000..8f17625 Binary files /dev/null and b/res/real_oneko.gif differ diff --git a/src/main.c b/src/main.c index faeaeeb..a64bf3e 100644 --- a/src/main.c +++ b/src/main.c @@ -97,6 +97,7 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) make_window_clickthrough(); set_override_redirect(); + SDL_SetDefaultTextureScaleMode(renderer, SDL_SCALEMODE_PIXELART); neko_init(renderer, window); diff --git a/src/neko.c b/src/neko.c index 0f40fb7..67211df 100644 --- a/src/neko.c +++ b/src/neko.c @@ -2,7 +2,6 @@ #include "common.h" #include -static SDL_Texture *texture = NULL; static int texture_width = 0; static int texture_height = 0; @@ -12,19 +11,40 @@ static float speed = 5.0; #define TIME_BEFORE_SPLEEP 3000 #define TIME_BEFORE_RUNNING 1000 +#define TIME_ANIM_INTERVAL 300 enum CatState { - SLEEPING, - RUNNING, - WAKING_UP, - STAND_BY, -} cat_state = RUNNING; + ST_SLEEPING, + ST_RUNNING, + ST_WAKING_UP, + ST_STAND_BY, +} cat_state = ST_RUNNING; + +enum CatFrames { + STAND_BY=0, + WAKING_UP=1, + UP=2, + DOWN=4, + LEFT=6, + RIGHT=8, + UP_LEFT=10, + UP_RIGHT=12, + DOWN_RIGHT=14, + DOWN_LEFT=16, + SLEEPING=18, +}; static int state_timer; +static int anim_timer = 0; +static int current_frame = 0; + +static float diffx, diffy; + +static IMG_Animation *anim; +static SDL_Texture **anim_textures; int neko_init(SDL_Renderer *renderer, SDL_Window *window){ - SDL_Surface *surface = NULL; - char *neko_bmp_path = NULL; + char *neko_gif_path = NULL; /* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D engines refer to these as "sprites." We'll do a static texture (upload once, draw many @@ -32,25 +52,26 @@ int neko_init(SDL_Renderer *renderer, SDL_Window *window){ /* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access. Load a .bmp into a surface, move it to a texture from there. */ - SDL_asprintf(&neko_bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */ - surface = SDL_LoadBMP(neko_bmp_path); - if (!surface) { - SDL_Log("Couldn't load bitmap: %s", SDL_GetError()); + SDL_asprintf(&neko_gif_path, "%sreal_oneko.gif", SDL_GetBasePath()); + anim = IMG_LoadAnimation(neko_gif_path); + if (!anim) { + SDL_Log("Couldn't load %s: %s\n", neko_gif_path, SDL_GetError()); return SDL_APP_FAILURE; } + SDL_free(neko_gif_path); /* done with this, the file is loaded. */ - SDL_free(neko_bmp_path); /* done with this, the file is loaded. */ + texture_width = anim->w; + texture_height = anim->h; - texture_width = surface->w; - texture_height = surface->h; - - texture = SDL_CreateTextureFromSurface(renderer, surface); - if (!texture) { - SDL_Log("Couldn't create static texture: %s", SDL_GetError()); + anim_textures = (SDL_Texture **)SDL_calloc(anim->count, sizeof(*anim_textures)); + if (!anim_textures) { + SDL_Log("Couldn't allocate textures\n"); + IMG_FreeAnimation(anim); return SDL_APP_FAILURE; } - - SDL_DestroySurface(surface); /* done with this, the texture has a copy of the pixels now. */ + for (int i = 0; i < anim->count; ++i) { + anim_textures[i] = SDL_CreateTextureFromSurface(renderer, anim->frames[i]); + } SDL_AddTimer(50, move_cat, window); } @@ -60,18 +81,74 @@ void neko_render(SDL_Renderer *renderer, SDL_Window *window){ dst_rect.x = catx; dst_rect.y = caty; - dst_rect.h = WINDOW_HEIGHT/10; - dst_rect.w = WINDOW_HEIGHT/10; - SDL_RenderTexture(renderer, texture, NULL, &dst_rect); + dst_rect.h = WINDOW_HEIGHT/15; + dst_rect.w = WINDOW_HEIGHT/15; + + int texture_index = 0; + switch (cat_state) + { + case ST_SLEEPING: + texture_index = SLEEPING+current_frame; + break; + case ST_WAKING_UP: + texture_index = WAKING_UP; + break; + case ST_STAND_BY: + texture_index = STAND_BY; + break; + case ST_RUNNING: + // We do this to know if our cat is moving in diagonals + double angle = fabs(atan((double) (diffy/diffx))); + if(angleSDL_PI_D/6){ // Diagonals + if(diffy<0){ + if(diffx<0){ + texture_index = DOWN_RIGHT+current_frame; + }else{ + texture_index = DOWN_LEFT+current_frame; + } + }else{ + if(diffx<0){ + texture_index = UP_RIGHT+current_frame; + }else{ + texture_index = UP_LEFT+current_frame; + } + } + }else{ // pas diagonals + if(fabs(diffy) > fabs(diffx)){ + if(diffy<0){ + texture_index = DOWN+current_frame; + }else{ + texture_index = UP+current_frame; + } + }else{ + if(diffx<0){ + texture_index = RIGHT+current_frame; + }else{ + texture_index = LEFT+current_frame; + } + } + } + break; + + default: + break; + } + + SDL_RenderTexture(renderer, anim_textures[texture_index], NULL, &dst_rect); + + if(SDL_GetTicks()-anim_timer > TIME_ANIM_INTERVAL){ + current_frame = (current_frame+1) % 2; + anim_timer=SDL_GetTicks(); + } } void neko_quit(){ - SDL_DestroyTexture(texture); + SDL_DestroyTexture(anim_textures[current_frame]); } Uint32 move_cat(void *window, SDL_TimerID timerID, Uint32 interval){ float mousex, mousey; - float diffx, diffy, hypo; + float hypo; int windowx, windowy; SDL_GetGlobalMouseState(&mousex, &mousey); @@ -82,31 +159,31 @@ Uint32 move_cat(void *window, SDL_TimerID timerID, Uint32 interval){ hypo = sqrt(diffx*diffx + diffy*diffy); switch (cat_state) { - case RUNNING: + case ST_RUNNING: if (hypo>50){ catx -= (diffx*speed/hypo); caty -= (diffy*speed/hypo); }else{ - cat_state = STAND_BY; + cat_state = ST_STAND_BY; state_timer = SDL_GetTicks(); } break; - case STAND_BY: + case ST_STAND_BY: if (hypo>50){ - cat_state = RUNNING; + cat_state = ST_RUNNING; }else if (SDL_GetTicks()-TIME_BEFORE_SPLEEP > state_timer){ - cat_state = SLEEPING; + cat_state = ST_SLEEPING; } break; - case SLEEPING: + case ST_SLEEPING: if (hypo>50){ - cat_state = WAKING_UP; + cat_state = ST_WAKING_UP; state_timer = SDL_GetTicks(); } break; - case WAKING_UP: + case ST_WAKING_UP: if (SDL_GetTicks()-TIME_BEFORE_RUNNING > state_timer){ - cat_state = RUNNING; + cat_state = ST_RUNNING; } break;