Skip to content

Commit c4e6707

Browse files
authored
Merge pull request #13 from RobLoach/slices
Add Slice Support
2 parents 0f03b36 + 6041f36 commit c4e6707

File tree

8 files changed

+177
-95
lines changed

8 files changed

+177
-95
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
cmake_minimum_required(VERSION 3.11)
22
project (raylib-aseprite
3-
VERSION 1.0.2
3+
VERSION 1.1.0
44
DESCRIPTION "raylib-aseprite"
55
HOMEPAGE_URL "https://github.com/robloach/raylib-aseprite"
66
LANGUAGES C)

README.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Load [Aseprite](https://www.aseprite.org) `.aseprite` files for animated sprites in [raylib](https://www.raylib.com).
44

5-
![examples/raylib-aseprite-example.png](examples/raylib-aseprite-example.png)
5+
![examples/raylib-aseprite-example.gif](examples/raylib-aseprite-example.gif)
66

77
## Features
88

@@ -13,13 +13,16 @@ Load [Aseprite](https://www.aseprite.org) `.aseprite` files for animated sprites
1313
- Adjust tag animation speed by using `tag.speed`
1414
- Pause tag animations by using `tag.pause`
1515
- Toggle whether animations will continue when they finish with `tag.loop`
16+
- Load [Aseprite slice](https://www.aseprite.org/docs/slices/) rectangles for collisions and bounds
1617

1718
## Usage
1819

1920
This is a header-only library. To use it, define `RAYLIB_ASEPRITE_IMPLEMENTATION` in one .c source file before including [*raylib-aseprite.h*](include). You will also have to link the raylib dependency.
2021

2122
### Example
2223

24+
The below is a basic example, see the [examples](examples) folder for more.
25+
2326
``` c
2427
#include "raylib.h"
2528

@@ -75,7 +78,6 @@ void TraceAseprite(Aseprite aseprite); // Display a
7578
Texture GetAsepriteTexture(Aseprite aseprite); // Retrieve the raylib texture associated with the aseprite
7679
int GetAsepriteWidth(Aseprite aseprite); // Get the width of the sprite
7780
int GetAsepriteHeight(Aseprite aseprite); // Get the height of the sprite
78-
int GetAsepriteTagCount(Aseprite aseprite); // Get the total amount of available tags
7981
void DrawAseprite(Aseprite aseprite, int frame, int posX, int posY, Color tint);
8082
void DrawAsepriteV(Aseprite aseprite, int frame, Vector2 position, Color tint);
8183
void DrawAsepriteEx(Aseprite aseprite, int frame, Vector2 position, float rotation, float scale, Color tint);
@@ -84,13 +86,21 @@ void DrawAsepritePro(Aseprite aseprite, int frame, Rectangle dest, Vector2 origi
8486
// Aseprite Tag functions
8587
AsepriteTag LoadAsepriteTag(Aseprite aseprite, const char* name); // Load an Aseprite tag animation sequence
8688
AsepriteTag LoadAsepriteTagFromIndex(Aseprite aseprite, int index); // Load an Aseprite tag animation sequence from its index
89+
int GetAsepriteTagCount(Aseprite aseprite); // Get the total amount of available tags
8790
bool IsAsepriteTagReady(AsepriteTag tag); // Check if the given Aseprite tag was loaded successfully
8891
void UpdateAsepriteTag(AsepriteTag* tag); // Update the tag animation frame
8992
AsepriteTag GenAsepriteTagDefault(); // Generate an empty Tag with sane defaults
9093
void DrawAsepriteTag(AsepriteTag tag, int posX, int posY, Color tint);
9194
void DrawAsepriteTagV(AsepriteTag tag, Vector2 position, Color tint);
9295
void DrawAsepriteTagEx(AsepriteTag tag, Vector2 position, float rotation, float scale, Color tint);
9396
void DrawAsepriteTagPro(AsepriteTag tag, Rectangle dest, Vector2 origin, float rotation, Color tint);
97+
98+
// Aseprite Slice functions
99+
AsepriteSlice LoadAsepriteSlice(Aseprite aseprite, const char* name); // Load a slice from an Aseprite based on its name.
100+
AsepriteSlice LoadAsperiteSliceFromIndex(Aseprite aseprite, int index); // Load a slice from an Aseprite based on its index.
101+
int GetAsepriteSliceCount(Aseprite aseprite); // Get the amount of slices that are defined in the Aseprite.
102+
bool IsAsepriteSliceReady(AsepriteSlice slice); // Return whether or not the given slice was found.
103+
AsepriteSlice GenAsepriteSliceDefault(); // Generate empty Aseprite slice data.
94104
```
95105
96106
## Development

examples/raylib-aseprite-example.c

Lines changed: 13 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -28,82 +28,22 @@ int main() {
2828
Aseprite george = LoadAseprite("resources/george.aseprite");
2929

3030
// Load the standing animations from the Aseprite tags.
31-
AsepriteTag standing[4] = {
32-
LoadAsepriteTag(george, "Stand-Up"),
33-
LoadAsepriteTag(george, "Stand-Right"),
34-
LoadAsepriteTag(george, "Stand-Down"),
35-
LoadAsepriteTag(george, "Stand-Left")
36-
};
37-
38-
// Load the moving animations from the Aseprite tags.
39-
AsepriteTag moving[4] = {
40-
LoadAsepriteTag(george, "Walk-Up"),
41-
LoadAsepriteTag(george, "Walk-Right"),
42-
LoadAsepriteTag(george, "Walk-Down"),
43-
LoadAsepriteTag(george, "Walk-Left")
44-
};
45-
46-
// Start the player facing down.
47-
int direction = 2;
31+
AsepriteTag walking = LoadAsepriteTag(george, "Walk-Down");
4832

49-
// Center the scaled player on the screen.
33+
// Center George on the screen.
5034
const float scale = 4;
51-
Vector2 playerPosition = {
35+
Vector2 position = {
5236
GetScreenWidth() / 2 - GetAsepriteWidth(george) / 2 * scale,
5337
GetScreenHeight() / 2 - GetAsepriteHeight(george) / 2 * scale
5438
};
55-
56-
// How fast the player should move around.
57-
const float speed = 2;
58-
59-
// Whether or not the player is actively moving.
60-
bool playerMoving;
6139
//--------------------------------------------------------------------------------------
6240

6341
while(!WindowShouldClose()) {
6442

6543
// Update
6644
//----------------------------------------------------------------------------------
67-
if (IsKeyDown(KEY_UP)) {
68-
direction = 0;
69-
playerMoving = true;
70-
}
71-
else if (IsKeyDown(KEY_RIGHT)) {
72-
direction = 1;
73-
playerMoving = true;
74-
}
75-
else if (IsKeyDown(KEY_DOWN)) {
76-
direction = 2;
77-
playerMoving = true;
78-
}
79-
else if (IsKeyDown(KEY_LEFT)) {
80-
direction = 3;
81-
playerMoving = true;
82-
}
83-
else {
84-
playerMoving = false;
85-
}
86-
87-
if (playerMoving) {
88-
// Update the active moving animation.
89-
UpdateAsepriteTag(&moving[direction]);
90-
91-
// Move the player.
92-
switch (direction) {
93-
case 0:
94-
playerPosition.y -= speed;
95-
break;
96-
case 1:
97-
playerPosition.x += speed;
98-
break;
99-
case 2:
100-
playerPosition.y += speed;
101-
break;
102-
case 3:
103-
playerPosition.x -= speed;
104-
break;
105-
}
106-
}
45+
// Update the active moving animation.
46+
UpdateAsepriteTag(&walking);
10747
//----------------------------------------------------------------------------------
10848

10949
// Draw
@@ -112,13 +52,14 @@ int main() {
11252
{
11353
ClearBackground(RAYWHITE);
11454

115-
// Draw either the moving, or standing animation.
116-
if (playerMoving) {
117-
DrawAsepriteTagEx(moving[direction], playerPosition, 0, scale, WHITE);
118-
}
119-
else {
120-
DrawAsepriteTagEx(standing[direction], playerPosition, 0, scale, WHITE);
121-
}
55+
// Draw one frame of George.
56+
DrawAseprite(george, 0, 100, 100, WHITE);
57+
DrawAseprite(george, 4, 100, 150, WHITE);
58+
DrawAseprite(george, 8, 100, 200, WHITE);
59+
DrawAseprite(george, 12, 100, 250, WHITE);
60+
61+
// Draw the walking animation.
62+
DrawAsepriteTagEx(walking, position, 0, scale, WHITE);
12263
}
12364
EndDrawing();
12465
//----------------------------------------------------------------------------------

examples/raylib-aseprite-example.gif

22.6 KB
Loading

include/raylib-aseprite.h

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ extern "C" {
4040

4141
typedef struct Aseprite Aseprite; // A loaded Aseprite file
4242
typedef struct AsepriteTag AsepriteTag; // A tag sprite animation within an Aseprite file
43+
typedef struct AsepriteSlice AsepriteSlice; // A slice is a defined region within the Asperite.
4344

4445
// Aseprite functions
4546
Aseprite LoadAseprite(const char* fileName); // Load an .aseprite file
@@ -50,7 +51,6 @@ void TraceAseprite(Aseprite aseprite); // Display a
5051
Texture GetAsepriteTexture(Aseprite aseprite); // Retrieve the raylib texture associated with the aseprite
5152
int GetAsepriteWidth(Aseprite aseprite); // Get the width of the sprite
5253
int GetAsepriteHeight(Aseprite aseprite); // Get the height of the sprite
53-
int GetAsepriteTagCount(Aseprite aseprite); // Get the total amount of available tags
5454
void DrawAseprite(Aseprite aseprite, int frame, int posX, int posY, Color tint);
5555
void DrawAsepriteV(Aseprite aseprite, int frame, Vector2 position, Color tint);
5656
void DrawAsepriteEx(Aseprite aseprite, int frame, Vector2 position, float rotation, float scale, Color tint);
@@ -59,6 +59,7 @@ void DrawAsepritePro(Aseprite aseprite, int frame, Rectangle dest, Vector2 origi
5959
// Aseprite Tag functions
6060
AsepriteTag LoadAsepriteTag(Aseprite aseprite, const char* name); // Load an Aseprite tag animation sequence
6161
AsepriteTag LoadAsepriteTagFromIndex(Aseprite aseprite, int index); // Load an Aseprite tag animation sequence from its index
62+
int GetAsepriteTagCount(Aseprite aseprite); // Get the total amount of available tags
6263
bool IsAsepriteTagReady(AsepriteTag tag); // Check if the given Aseprite tag was loaded successfully
6364
void UpdateAsepriteTag(AsepriteTag* tag); // Update the tag animation frame
6465
AsepriteTag GenAsepriteTagDefault(); // Generate an empty Tag with sane defaults
@@ -67,6 +68,13 @@ void DrawAsepriteTagV(AsepriteTag tag, Vector2 position, Color tint);
6768
void DrawAsepriteTagEx(AsepriteTag tag, Vector2 position, float rotation, float scale, Color tint);
6869
void DrawAsepriteTagPro(AsepriteTag tag, Rectangle dest, Vector2 origin, float rotation, Color tint);
6970

71+
// Aseprite Slice functions
72+
AsepriteSlice LoadAsepriteSlice(Aseprite aseprite, const char* name); // Load a slice from an Aseprite based on its name.
73+
AsepriteSlice LoadAsperiteSliceFromIndex(Aseprite aseprite, int index); // Load a slice from an Aseprite based on its index.
74+
int GetAsepriteSliceCount(Aseprite aseprite); // Get the amount of slices that are defined in the Aseprite.
75+
bool IsAsepriteSliceReady(AsepriteSlice slice); // Return whether or not the given slice was found.
76+
AsepriteSlice GenAsepriteSliceDefault(); // Generate empty Aseprite slice data.
77+
7078
#ifdef __cplusplus
7179
}
7280
#endif
@@ -152,6 +160,17 @@ struct AsepriteTag {
152160
ase_tag_t* tag; // The active tag to act upon
153161
};
154162

163+
/**
164+
* Slice data for the Aseprite.
165+
*
166+
* @see LoadAsepriteSlice()
167+
* @see https://www.aseprite.org/docs/slices/
168+
*/
169+
struct AsepriteSlice {
170+
char* name; // The name of the slice.
171+
Rectangle bounds; // The rectangle outer bounds for the slice.
172+
};
173+
155174
/**
156175
* Load an .aseprite file through its memory data.
157176
*
@@ -652,6 +671,80 @@ bool IsAsepriteTagReady(AsepriteTag tag) {
652671
return tag.tag != 0;
653672
}
654673

674+
/**
675+
* Load a slice from an Aseprite based on its name.
676+
*
677+
* @param name The name of the slice to find.
678+
*
679+
* @return The loaded slice, or an empty one if not found.
680+
*/
681+
AsepriteSlice LoadAsepriteSlice(Aseprite aseprite, const char* name) {
682+
if (aseprite.ase == NULL) {
683+
TraceLog(LOG_WARNING, "ASEPRITE: Cannot load slice on empty aseprite");
684+
return GenAsepriteSliceDefault();
685+
}
686+
for (int i = 0; i < aseprite.ase->slice_count; i++) {
687+
ase_slice_t* slice = &aseprite.ase->slices[i];
688+
if (TextIsEqual(name, slice->name)) {
689+
return LoadAsperiteSliceFromIndex(aseprite, i);
690+
}
691+
}
692+
693+
return GenAsepriteSliceDefault();
694+
}
695+
696+
/**
697+
* Load a slice from an Aseprite based on its index.
698+
*
699+
* @param index The index of the slice to load.
700+
*
701+
* @return The loaded slice, or an empty one if not found.
702+
*/
703+
AsepriteSlice LoadAsperiteSliceFromIndex(Aseprite aseprite, int index) {
704+
if (aseprite.ase == NULL) {
705+
TraceLog(LOG_WARNING, "ASEPRITE: Cannot load slice index from empty aseprite");
706+
return GenAsepriteSliceDefault();
707+
}
708+
if (index < aseprite.ase->slice_count) {
709+
AsepriteSlice output;
710+
ase_slice_t* slice = &aseprite.ase->slices[index];
711+
output.bounds.x = (float)slice->origin_x;
712+
output.bounds.y = (float)slice->origin_y;
713+
output.bounds.width = (float)slice->w;
714+
output.bounds.height = (float)slice->h;
715+
output.name = (char*)slice->name;
716+
return output;
717+
}
718+
719+
return GenAsepriteSliceDefault();
720+
}
721+
722+
/**
723+
* Generate empty Aseprite slice data.
724+
*/
725+
AsepriteSlice GenAsepriteSliceDefault() {
726+
AsepriteSlice slice;
727+
slice.name = "";
728+
slice.bounds = (Rectangle){0, 0, 0, 0};
729+
return slice;
730+
}
731+
732+
/**
733+
* Get the amount of slices that are defined in the Aseprite.
734+
*
735+
* @return The amount of slices.
736+
*/
737+
int GetAsepriteSliceCount(Aseprite aseprite) {
738+
return aseprite.ase->slice_count;
739+
}
740+
741+
/**
742+
* Return whether or not the given slice was found.
743+
*/
744+
bool IsAsepriteSliceReady(AsepriteSlice slice) {
745+
return TextLength(slice.name) != 0;
746+
}
747+
655748
#ifdef __cplusplus
656749
}
657750
#endif

0 commit comments

Comments
 (0)