mirror of
https://github.com/Kapendev/parin.git
synced 2025-04-26 13:09:56 +03:00
Added an animation struct for sprites.
This commit is contained in:
parent
b4b47d8dea
commit
dbceb425d5
11 changed files with 57 additions and 39 deletions
|
@ -11,7 +11,7 @@ void ready() {
|
|||
}
|
||||
|
||||
bool update(float dt) {
|
||||
drawDebugText("Hello world!", Vec2(8.0));
|
||||
drawDebugText("Hello world!", Vec2(8));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
2
TOUR.md
2
TOUR.md
|
@ -12,7 +12,7 @@ void ready() {
|
|||
}
|
||||
|
||||
bool update(float dt) {
|
||||
drawDebugText("Hello world!", Vec2(8.0));
|
||||
drawDebugText("Hello world!", Vec2(8));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Examples
|
||||
|
||||
> [!NOTE]
|
||||
> For examples that use sprites, you must download the [atlas.png](atlas.png) file and save it in your project's assets folder.
|
||||
> For examples that use textures, the [atlas.png](atlas.png) file must be downloaded and saved in the project's assets folder.
|
||||
|
||||
## [Hello](hello.d)
|
||||
|
||||
|
@ -23,10 +23,10 @@ This example shows how to use the camera structure of Popka.
|
|||
|
||||
This example shows how to use the Popka dialogue system.
|
||||
|
||||
## [Follower](follower.d)
|
||||
|
||||
This example shows how to create an animated character that follows the mouse.
|
||||
|
||||
## [Map](map.d)
|
||||
|
||||
This example shows how to use the tile map structure of Popka.
|
||||
|
||||
## [Follower](follower.d)
|
||||
|
||||
This example shows how to create an animated character that follows the mouse.
|
||||
|
|
|
@ -18,12 +18,12 @@ bool update(float dt) {
|
|||
// Draw the game world.
|
||||
auto cameraArea = Rect(camera.position, resolution).area(camera.hook).subAll(3);
|
||||
camera.attach();
|
||||
drawDebugText("Move with arrow keys.", Vec2(8.0));
|
||||
drawDebugText("Move with arrow keys.", Vec2(8));
|
||||
drawRect(cameraArea, Color(50, 50, 40, 130));
|
||||
camera.detach();
|
||||
|
||||
// Draw the game UI.
|
||||
drawDebugText("I am UI!", Vec2(8.0));
|
||||
drawDebugText("I am UI!", Vec2(8));
|
||||
drawDebugText("+", resolution * Vec2(0.5));
|
||||
drawDebugText("+", resolution * Vec2(0.5) + (cameraTarget - camera.position));
|
||||
return false;
|
||||
|
|
|
@ -48,9 +48,9 @@ bool update(float dt) {
|
|||
}
|
||||
drawRect(player);
|
||||
if (coins.length == 0) {
|
||||
drawDebugText("You collected all the coins!", Vec2(8.0));
|
||||
drawDebugText("You collected all the coins!", Vec2(8));
|
||||
} else {
|
||||
drawDebugText("Coins: {}/{}\nMove with arrow keys.".format(maxCoinCount - coins.length, maxCoinCount), Vec2(8.0));
|
||||
drawDebugText("Coins: {}/{}\nMove with arrow keys.".format(maxCoinCount - coins.length, maxCoinCount), Vec2(8));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -63,9 +63,9 @@ bool update(float dt) {
|
|||
drawDebugText(" | {}".format(choice), choicePosition);
|
||||
}
|
||||
} else if (dialogue.canUpdate) {
|
||||
drawDebugText("{}: {}".format(dialogue.actor, dialogue.text), Vec2(8.0));
|
||||
drawDebugText("{}: {}".format(dialogue.actor, dialogue.text), Vec2(8));
|
||||
} else {
|
||||
drawDebugText("The dialogue has ended.", Vec2(8.0));
|
||||
drawDebugText("The dialogue has ended.", Vec2(8));
|
||||
}
|
||||
|
||||
// Draw the game info.
|
||||
|
|
|
@ -3,9 +3,8 @@ import popka;
|
|||
|
||||
// The game variables.
|
||||
auto atlas = TextureId();
|
||||
auto sprite = Sprite(16, 16, 0, 128, 2, 8);
|
||||
auto sprite = Sprite(16, 16, 0, 128, SpriteAnimation(0, 2, 6));
|
||||
auto spritePosition = Vec2();
|
||||
auto spriteSlowdown = 0.2;
|
||||
|
||||
void ready() {
|
||||
lockResolution(320, 180);
|
||||
|
@ -18,7 +17,7 @@ void ready() {
|
|||
|
||||
bool update(float dt) {
|
||||
// Move the sprite around in a smooth way.
|
||||
spritePosition = spritePosition.moveToWithSlowdown(mouseScreenPosition, Vec2(dt), spriteSlowdown);
|
||||
spritePosition = spritePosition.moveToWithSlowdown(mouseScreenPosition, Vec2(dt), 0.2);
|
||||
|
||||
// Update the frame of the sprite.
|
||||
auto isWaiting = spritePosition.distanceTo(mouseScreenPosition) < 0.2;
|
||||
|
@ -28,14 +27,23 @@ bool update(float dt) {
|
|||
sprite.update(dt);
|
||||
}
|
||||
|
||||
// Check if 1, 2, or 3 is pressed and change the character.
|
||||
foreach (i, digit; digitChars[1 .. 4]) {
|
||||
if (digit.isPressed) {
|
||||
sprite.animation.frameRow = cast(ubyte) i;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the drawing options for the sprite.
|
||||
auto options = DrawOptions();
|
||||
options.scale = Vec2(2);
|
||||
options.hook = Hook.center;
|
||||
options.flip = (spritePosition.directionTo(mouseScreenPosition).x > 0) ? Flip.x : Flip.none;
|
||||
// Draw the sprite and the mouse position.
|
||||
|
||||
// Draw the sprite, the mouse position and some info.
|
||||
drawSprite(atlas, sprite, spritePosition, options);
|
||||
drawVec2(mouseScreenPosition, 8, isWaiting ? blank : white.alpha(130));
|
||||
drawVec2(mouseScreenPosition, 8, isWaiting ? blank : white.alpha(150));
|
||||
drawDebugText("Press 1, 2 or 3 to change the character.", Vec2(8));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ void ready() {
|
|||
// The update function. This is called every frame while the game is running.
|
||||
// If true is returned, then the game will stop running.
|
||||
bool update(float dt) {
|
||||
drawDebugText("Hello world!", Vec2(8.0));
|
||||
drawDebugText("Hello world!", Vec2(8));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,8 @@ void ready() {
|
|||
bool update(float dt) {
|
||||
// Set the drawing options for the tile map.
|
||||
auto options = DrawOptions();
|
||||
options.scale = Vec2(2.0f);
|
||||
options.scale = Vec2(2);
|
||||
|
||||
// Draw the tile map.
|
||||
drawTileMap(atlas, tileMap, Vec2(), Camera(), options);
|
||||
return false;
|
||||
|
|
|
@ -19,7 +19,7 @@ void ready() {
|
|||
}
|
||||
|
||||
bool update(float dt) {
|
||||
drawDebugText("Hello world!", Vec2(8.0));
|
||||
drawDebugText("Hello world!", Vec2(8));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,28 +15,36 @@ import popka.engine;
|
|||
|
||||
// TODO: Think about gaps in an atlas texture.
|
||||
|
||||
struct Sprite {
|
||||
int width;
|
||||
int height;
|
||||
int atlasLeft;
|
||||
int atlasTop;
|
||||
int frameCount = 1;
|
||||
float frameSpeed = 1.0f;
|
||||
float frameProgress = 0.0f;
|
||||
struct SpriteAnimation {
|
||||
ubyte frameRow;
|
||||
ubyte frameCount = 1;
|
||||
ubyte frameSpeed = 1;
|
||||
|
||||
@safe @nogc nothrow:
|
||||
|
||||
this(int width, int height, int atlasLeft, int atlasTop, int frameCount = 1, float frameSpeed = 1.0f) {
|
||||
this(ubyte frameRow, ubyte frameCount, ubyte frameSpeed) {
|
||||
this.frameRow = frameRow;
|
||||
this.frameCount = frameCount;
|
||||
this.frameSpeed = frameSpeed;
|
||||
}
|
||||
}
|
||||
|
||||
struct Sprite {
|
||||
int width;
|
||||
int height;
|
||||
ushort atlasLeft;
|
||||
ushort atlasTop;
|
||||
float frameProgress = 0.0f;
|
||||
SpriteAnimation animation;
|
||||
|
||||
@safe @nogc nothrow:
|
||||
|
||||
this(int width, int height, ushort atlasLeft, ushort atlasTop, SpriteAnimation animation = SpriteAnimation()) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.atlasLeft = atlasLeft;
|
||||
this.atlasTop = atlasTop;
|
||||
this.frameCount = frameCount;
|
||||
this.frameSpeed = frameSpeed;
|
||||
}
|
||||
|
||||
this(int width, int height) {
|
||||
this(width, height, 0, 0);
|
||||
this.animation = animation;
|
||||
}
|
||||
|
||||
int frame() {
|
||||
|
@ -48,19 +56,20 @@ struct Sprite {
|
|||
}
|
||||
|
||||
void update(float dt) {
|
||||
frameProgress = wrap(frameProgress + frameSpeed * dt, 0.0f, frameCount);
|
||||
frameProgress = wrap(frameProgress + animation.frameSpeed * dt, 0.0f, animation.frameCount);
|
||||
}
|
||||
}
|
||||
|
||||
void drawSprite(Texture texture, Sprite sprite, Vec2 position, DrawOptions options = DrawOptions()) {
|
||||
auto top = sprite.atlasTop + sprite.animation.frameRow * sprite.height;
|
||||
auto gridWidth = max(texture.width - sprite.atlasLeft, 0) / sprite.width;
|
||||
auto gridHeight = max(texture.height - sprite.atlasTop, 0) / sprite.height;
|
||||
auto gridHeight = max(texture.height - top, 0) / sprite.height;
|
||||
if (gridWidth == 0 || gridHeight == 0) {
|
||||
return;
|
||||
}
|
||||
auto row = sprite.frame / gridWidth;
|
||||
auto col = sprite.frame % gridWidth;
|
||||
auto area = Rect(sprite.atlasLeft + col * sprite.width, sprite.atlasTop + row * sprite.height, sprite.width, sprite.height);
|
||||
auto area = Rect(sprite.atlasLeft + col * sprite.width, top + row * sprite.height, sprite.width, sprite.height);
|
||||
drawTextureArea(texture, area, position, options);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue