#include "common.h"
#include <math.h>
-static SDL_Texture *texture = NULL;
static int texture_width = 0;
static int texture_height = 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
/* 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 = surface->w;
- texture_height = surface->h;
+ texture_width = anim->w;
+ texture_height = anim->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);
}
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(angle<SDL_PI_D/3 && angle>SDL_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);
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;