/*! * \brief * Starts a tilemap animation * * \param index * Id of the animation to set (0 <= id < num_animations) * * \param nlayer * Id of the layer to animate (0 <= id < num_layers) * * \param sequence * Reference of the sequence to assign * * \see * Animations */ bool TLN_SetTilemapAnimation (int index, int nlayer, TLN_Sequence sequence) { Animation* animation; if (index >= engine->numanimations) { TLN_SetLastError (TLN_ERR_IDX_ANIMATION); return false; } if (nlayer >= engine->numlayers) { TLN_SetLastError (TLN_ERR_IDX_LAYER); return false; } /* validate type */ if (!CheckBaseObject (sequence, OT_SEQUENCE)) return false; animation = &engine->animations[index]; SetAnimation (animation, sequence, TYPE_TILEMAP); animation->idx = nlayer; TLN_SetLastError (TLN_ERR_OK); return true; }
/*! * \brief * Starts a sprite animation * * \param index * Id of the animation to set (0 <= id < num_animations) * * \param nsprite * If of the sprite to animate (0 <= id < num_sprites) * * \param sequence * Reference of the sequence to assign * * \param loop * amount of times to loop, 0=infinite * * \see * Animations */ bool TLN_SetSpriteAnimation (int index, int nsprite, TLN_Sequence sequence, int loop) { Animation* animation; if (index >= engine->numanimations) { TLN_SetLastError (TLN_ERR_IDX_ANIMATION); return false; } if (nsprite >= engine->numsprites) { TLN_SetLastError (TLN_ERR_IDX_SPRITE); return false; } /* validate type */ if (!CheckBaseObject (sequence, OT_SEQUENCE)) return false; animation = &engine->animations[index]; SetAnimation (animation, sequence, TYPE_SPRITE); animation->idx = nsprite; animation->loop = loop; TLN_SetLastError (TLN_ERR_OK); return true; }
/*! * \brief * Load image file (8-bit BMP or PNG) * * \param filename * File name with the image * * \returns * Handler to the loaded image or NULL if error * * \see * TLN_DeleteBitmap() */ TLN_Bitmap TLN_LoadBitmap (char *filename) { TLN_Bitmap bitmap; if (!CheckFile (filename)) { TLN_SetLastError (TLN_ERR_FILE_NOT_FOUND); return NULL; } /* try png, else bmp*/ bitmap = LoadPNG (filename); if (bitmap == NULL) bitmap = LoadBMP (filename); /* bitmap loaded */ if (bitmap) { /* accept only 8 bpp */ int bpp = TLN_GetBitmapDepth (bitmap); if (bpp == 8) TLN_SetLastError (TLN_ERR_OK); else { TLN_DeleteBitmap (bitmap); bitmap = NULL; } } if (!bitmap) TLN_SetLastError (TLN_ERR_WRONG_FORMAT); return bitmap; }
/** * \brief * Checks the state of the specified animation * * \param index * Id of the animation to check (0 <= id < num_animations) * * \returns * true if animation is running, false if it's finished or inactive */ bool TLN_GetAnimationState (int index) { if (index >= engine->numanimations) { TLN_SetLastError (TLN_ERR_IDX_ANIMATION); return false; } TLN_SetLastError (TLN_ERR_OK); return engine->animations[index].enabled; }
/*! * \brief * Creates a new sequence for the animation engine * * \param name * String with an unique name to query later * * \param target * For tileset animations, the tile index to animate * * \param count * Number of frames * * \param frames * Array of TLN_Frame items with indexes and delays * * \returns * Reference to the new sequence or NULL if error * * \remarks * Use this function to create tileset or sprite animations * * \see * TLN_SetTilemapAnimation(), TLN_SetSpriteAnimation() */ TLN_Sequence TLN_CreateSequence (const char* name, int target, int count, TLN_SequenceFrame* frames) { int size; TLN_Sequence sequence; TLN_SequenceFrame* frame; size = count*sizeof(TLN_SequenceFrame); sequence = CreateBaseObject (OT_SEQUENCE, sizeof(struct Sequence) + size); if (!sequence) return NULL; if (name) { sequence->hash = hash(0, name, strlen(name)); strncpy (sequence->name, name, 32); } sequence->target = target; sequence->count = count; frame = (TLN_SequenceFrame*)&sequence->data; memcpy (frame, frames, sizeof(TLN_SequenceFrame)*count); TLN_SetLastError (TLN_ERR_OK); return sequence; }
/*! * \brief * Sets the playback speed of a given animation * * \param index * Id of the animation to set (0 <= id < num_animations) * * \param delay * New delay between frames to assign * * Each sequence has its own delay set in the sqx file. However sometimes it's convenient * to speed up or down the playback speed in realtime, for example for a character that is * accelerating. * * \remarks * The meaning of the delay value (i.e. its units) is application dependant. It can usually be frames * or milliseconds. Make sure that its units match the ones insode the sqx file and the ones * passed to the TLN_UpdateFrame() * * \see * Animations, TLN_UpdateFrame() */ bool TLN_SetAnimationDelay (int index, int delay) { Animation* animation; if (index >= engine->numanimations) { TLN_SetLastError (TLN_ERR_IDX_ANIMATION); return false; } animation = &engine->animations[index]; animation->delay = delay; TLN_SetLastError (TLN_ERR_OK); return true; }
/*! * \brief * Creates a color cycle sequence for palette animation * * \param name * String with an unique name to query later * * \param count * Number of color strips * * \param strips * Array of color strips to assign * * \returns * Reference to the created cycle or NULL if error * * \remarks * Use this function to create advanced palette animation effects * * \see * TLN_ColorStrip(), TLN_SetPaletteAnimation() */ TLN_Sequence TLN_CreateCycle (const char* name, int count, TLN_ColorStrip* strips) { int size, c; TLN_Sequence sequence; TLN_ColorStrip* srcstrip; struct Strip* dststrip; size = count*sizeof(struct Strip); sequence = CreateBaseObject (OT_SEQUENCE, sizeof(struct Sequence) + size); if (!sequence) return NULL; if (name) { sequence->hash = hash(0, name, strlen(name)); strncpy (sequence->name, name, 32); } sequence->count = count; srcstrip = strips; dststrip = (struct Strip*)&sequence->data; for (c=0; c<count; c++) { dststrip->delay = srcstrip->delay; dststrip->first = srcstrip->first; dststrip->count = srcstrip->count; dststrip->dir = srcstrip->dir; srcstrip++; dststrip++; } TLN_SetLastError (TLN_ERR_OK); return sequence; }
/*! * \brief * Disables the animation so it stops playing and returns it to the list of available animations * * \param index * Id of the animation to set (0 <= id < num_animations) * * \see * Animations */ bool TLN_DisableAnimation (int index) { Animation* animation; if (index >= engine->numanimations) { TLN_SetLastError (TLN_ERR_IDX_ANIMATION); return false; } animation = &engine->animations[index]; animation->enabled = false; animation->type = TYPE_NONE; animation->sequence = NULL; TLN_SetLastError (TLN_ERR_OK); return true; }
/*! * \brief * Loads a palette from a standard .act file * * \param filename * ACT file containing the palette to load * * \returns * A reference to the newly loaded palette, or NULL if error * * \remarks * Palettes are also automatically created when loading tilesets and spritesets. * Use the functions TLN_GetTilesetPalette() and TLN_GetSpritesetPalette() to retrieve them. * * \see * TLN_GetTilesetPalette(), TLN_GetSpritesetPalette() */ TLN_Palette TLN_LoadPalette (char *filename) { FILE *pf; TLN_Palette palette = NULL; int size; int c; /* open file */ pf = fopen (filename, "rb"); if (!pf) { TLN_SetLastError (TLN_ERR_FILE_NOT_FOUND); return NULL; } /* check size */ fseek (pf, 0, SEEK_END); size = ftell (pf); /* load trailing and get number of entries */ if (size == ACT_SIZE) { fseek (pf, - (int)sizeof(trailing), SEEK_END); fread (&trailing, sizeof(trailing), 1, pf); trailing.entries = SWAP(trailing.entries); trailing.transparent = SWAP(trailing.transparent); } else trailing.entries = size/3; /* create palette and load from file */ palette = TLN_CreatePalette (trailing.entries); fseek (pf, 0, SEEK_SET); for (c=0; c<trailing.entries; c++) { BYTE src[3]; fread (src, sizeof(src), 1, pf); TLN_SetPaletteColor (palette, c, src[0], src[1], src[2]); } fclose (pf); TLN_SetLastError (TLN_ERR_OK); return palette; }
/*! * \brief * Starts a palette animation * * \param index * Id of the animation to set (0 <= id < num_animations) * * \param palette * Reference of the palette to be animated * * \param sequence * Reference of the sequence to assign * * \param blend * true for smooth frame interpolation, false for classic, discrete mode */ bool TLN_SetPaletteAnimation (int index, TLN_Palette palette, TLN_Sequence sequence, bool blend) { Animation* animation; int c; struct Strip* strips; TLN_SetLastError (TLN_ERR_OK); if (index >= engine->numanimations) { TLN_SetLastError (TLN_ERR_IDX_ANIMATION); return false; } animation = &engine->animations[index]; if (animation->sequence == sequence) return true; /* validate type */ if (!CheckBaseObject (palette, OT_PALETTE) || !CheckBaseObject (sequence, OT_SEQUENCE)) return false; SetAnimation (animation, sequence, TYPE_PALETTE); animation->palette = palette; animation->blend = blend; /* start timers */ strips = (struct Strip*)&sequence->data; for (c=0; c<sequence->count; c++) { strips[c].timer = 0; strips[c].t0 = 0; } /* create auxiliary palette */ if (animation->srcpalette == NULL) animation->srcpalette = TLN_CreatePalette (256); CopyBaseObject (animation->srcpalette, palette); return true; }
/*! * \brief * Deletes the sequence and frees resources * * \param sequence * Reference to the sequence to be deleted * * \remarks * Don't delete an active sequence! */ bool TLN_DeleteSequence (TLN_Sequence sequence) { if (CheckBaseObject (sequence, OT_SEQUENCE)) { DeleteBaseObject (sequence); TLN_SetLastError (TLN_ERR_OK); return true; } else return false; }
/*! * \brief * Sets the source palette of a color cycle animation * * \param index * Id of the animation to set (0 <= id < num_animations) * * \param palette * Reference of the palette to assign * * \remarks * Use this function to change the palette assigned to a color cycle animation running. * This is useful to combine color cycling and palette interpolation at the same time */ bool TLN_SetPaletteAnimationSource (int index, TLN_Palette palette) { Animation* animation; if (index >= engine->numanimations) { TLN_SetLastError (TLN_ERR_IDX_ANIMATION); return false; } if (!CheckBaseObject (palette, OT_PALETTE)) return false; animation = &engine->animations[index]; CopyBaseObject (animation->srcpalette, palette); CopyBaseObject (animation->palette, palette); TLN_SetLastError (TLN_ERR_OK); return true; }
/*! * \brief * Finds an available (unused) animation * * \returns * Index of the first unused animation (starting from 0) or -1 if none found */ int TLN_GetAvailableAnimation (void) { int c; TLN_SetLastError (TLN_ERR_OK); for (c=0; c<engine->numanimations; c++) { if (!engine->animations[c].enabled) return c; } return -1; }
/*! * \brief * Creates a duplicate of the specified sequence * * \param src * Sequence to clone * * \returns * A reference to the newly cloned sequence, or NULL if error * * \see * TLN_FindSequence() */ TLN_Sequence TLN_CloneSequence (TLN_Sequence src) { TLN_Sequence sequence; if (!CheckBaseObject (src, OT_SEQUENCE)) return NULL; sequence = CloneBaseObject (src); if (sequence) { TLN_SetLastError (TLN_ERR_OK); return sequence; } else return NULL; }
// TODO JNIEXPORT jint JNICALL Java_Tilengine_CreateCycle (JNIEnv* env, jobject thisobj, jstring name, jint num_strips, jobjectArray strips) { TLN_SetLastError (TLN_ERR_UNSUPPORTED); return 0; }
// TODO JNIEXPORT jboolean JNICALL Java_Tilengine_SetLayerAffineTransform (JNIEnv* env, jobject thisobj, jint nlayer, jobject aff) { TLN_SetLastError (TLN_ERR_UNSUPPORTED); return false; }
// TODO JNIEXPORT jint JNICALL Java_Tilengine_CreateTilemap (JNIEnv* env, jobject thisobj, jint rows, jint cols, jobjectArray tiles) { TLN_SetLastError (TLN_ERR_UNSUPPORTED); return 0; }
JNIEXPORT void JNICALL Java_Tilengine_SetLastError (JNIEnv* env, jobject thisobj, jint error) { TLN_SetLastError (error); }
/*! * \brief * Loads a spriteset from a png/txt file pair * * \param name * Base name of the files containing the spriteset * * \returns * Reference to the newly loaded spriteset or NULL if error * * \remarks * The spriteset comes in a pair of files called name.png and name.txt. The png file contains * the spriteset, whereas the txt contains the coordinates of the rectangles that define individual sprites. * These files can be created wit the spritesheet packer tool (http://spritesheetpacker.codeplex.com/) * \remarks * An associated palette is also created, it can be obtained calling TLN_GetSpritesetPalette() */ TLN_Spriteset TLN_LoadSpriteset (const char* name) { FILE *pf; char filename[64]; char line[64]; int entries = 0; TLN_Bitmap bitmap; TLN_Spriteset spriteset; TLN_Rect *rects, *rect; int c; /* load png file */ sprintf (filename, "%s.png", name); bitmap = TLN_LoadBitmap (filename); if (!bitmap) return NULL; /* load txt file */ sprintf (filename, "%s.txt", name); pf = FileOpen (filename); if (!pf) { TLN_DeleteBitmap (bitmap); TLN_SetLastError (TLN_ERR_FILE_NOT_FOUND); return NULL; } /* count lines */ while (fgets (line, 64, pf)) entries++; rects = malloc (sizeof(TLN_Rect)*entries); if (!rects) { TLN_DeleteBitmap (bitmap); TLN_SetLastError (TLN_ERR_OUT_OF_MEMORY); fclose (pf); return NULL; } /* read entries */ fseek (pf, 0, SEEK_SET); for (c=0; c<entries; c++) { char* equals; char imagename[64]; /* lee linea */ fgets (line, 64, pf); rect = &rects[c]; /* formato SpriteSheetPacker: name = x y w h */ equals = strchr (line, '='); if (equals != NULL) { sscanf (line, "%s = %d %d %d %d", imagename, &rect->x, &rect->y, &rect->w, &rect->h); continue; } /* formato Leshy SpriteSheet Tool csv: name,x,y,w,h */ equals = strchr (line, ','); if (equals != NULL) { char* del = line; while (*del) { if (*del == ',') *del = ' '; del++; } sscanf (line, "%s %d %d %d %d", imagename, &rect->x, &rect->y, &rect->w, &rect->h); continue; } } fclose (pf); /* create */ spriteset = TLN_CreateSpriteset ( entries, rects, TLN_GetBitmapPtr (bitmap, 0,0), TLN_GetBitmapWidth (bitmap), TLN_GetBitmapHeight (bitmap), TLN_GetBitmapPitch (bitmap), TLN_ClonePalette(TLN_GetBitmapPalette(bitmap)) ); /* free resources */ free (rects); TLN_DeleteBitmap (bitmap); if (spriteset) TLN_SetLastError (TLN_ERR_OK); else TLN_SetLastError (TLN_ERR_OUT_OF_MEMORY); return spriteset; }