能帮到你的话,就给个赞吧 😘
#pragma once
#include "atlas.h"
#include "timer.h"
#include "vector2.h"
#include "util.h"
#include <vector>
#include <functional>
class Animation {
//兼容任意大小的图片
struct Frame{
Frame() = default;
Frame(IMAGE* img, const Rect& src) : img(img), src(src) {}
IMAGE* img = nullptr;
Rect src;
};
public:
enum AnchorMode {
Centered, //居中
BottomCentered //底部居中
};
public:
Animation();
public:
void play(int deltaT); //播放
void render(); //渲染
public:
void setAnchorMode(const AnchorMode& anchorMode);
void setPosition(const Vector2& position);
void reset();
void setIsLoop(bool isLoop);
void setInterval(int interval);
void setPlaybackTask(const std::function<void()>& playbackTask);
void addFrames(IMAGE* img, int num); //加载一张长条动画
void addFrames(Atlas* atlas); //加载一个图集
private:
std::vector<Frame> frames; //图集
int index = 0; //帧索引
Timer timer; //定时器——推动帧索引
Vector2 position; //动画位置
bool isLoop = true; //动画是否循环
std::function<void()> playbackTask; //播放完后的任务
AnchorMode anchorMode = Centered; //position位于图片的脚底还是中心
};
Animation::Animation(){
timer.setIsOneShot(false);
//定时器负责向前播放
timer.setTimedTask([&] {
index++;
if (index == frames.size()) {
index = isLoop ? 0 : frames.size() - 1;
if (!isLoop && playbackTask)
playbackTask();
}
});
}
void Animation::play(int deltaT){
timer.timing(deltaT);
}
void Animation::render(){
const auto& frame = frames[index];
Rect dst;
//position 位于 图片中心 or 底部
dst.x = position.x - frame.src.w / 2;
dst.y = anchorMode == Centered ? position.y - frame.src.h / 2 : position.y - frame.src.h;
dst.w = frame.src.w;
dst.h = frame.src.h;
putImageEx(frame.img, &dst, &frame.src);
}
void Animation::setAnchorMode(const AnchorMode& anchorMode){
this->anchorMode = anchorMode;
}
inline void Animation::setPosition(const Vector2& position){
this->position = position;
}
void Animation::reset() {
index = 0;
timer.reSet();
}
void Animation::setIsLoop(bool isLoop) {
this->isLoop = isLoop;
}
void Animation::setInterval(int interval) {
timer.setTimer(interval);
}
void Animation::setPlaybackTask(const std::function<void()>& playbackTask){
this->playbackTask = playbackTask;
}
//加载一张长条动画
void Animation::addFrames(IMAGE* img, int num){
auto frameWidth = img->getwidth() / num;
auto frameHeight = img->getheight();
for (auto i = 0; i < num; i++) {
Rect src;
src.x = i * frameWidth;
src.y = 0;
src.w = frameWidth;
src.h = frameHeight;
frames.emplace_back(img, src);
}
}
//加载一个图集
void Animation::addFrames(Atlas* atlas){
Rect src;
for (auto i = 0; i < atlas->getSize(); i++) {
auto img = atlas->getImage(i);
auto frameWidth = img->getwidth();
auto frameHeight = img->getheight();
src.x = 0;
src.y = 0;
src.w = frameWidth;
src.h = frameHeight;
frames.emplace_back(img, src);
}
}
#pragma once
#include <cmath>
class Vector2 {
public:
Vector2() = default;
Vector2(float x, float y);
public:
const Vector2& operator+(const Vector2& other) const;
const Vector2& operator-(const Vector2& other) const;
float operator*(const Vector2& other) const;
const Vector2& operator*(const float val) const;
void operator+=(const Vector2& other);
void operator-=(const Vector2& other);
void operator*=(const float val);
public:
float lenth();
const Vector2& normalize() const;
public:
float x = 0, y = 0;
};
#pragma once
#include <functional>
class Timer {
public:
Timer() = default;
Timer(int timerMs, bool isOneShot, const std::function<void()>& timedTask);
public:
void setTimer(int timerMs); //设置定时时间
void setIsOneShot(bool isOneShot); //设置任务单次/循环触发
void setTimedTask(const std::function<void()>& timedTask); //设置定时任务
public:
void pause(); //暂停
void resume(); //恢复
void reSet(); //重置
void timing(int deltaT); //计时
private:
int timer = 0; //定时时间
int time = 0; //计时器已经经过的时间
bool isPause = false;
bool isOneShot = false; //任务是否只触发一次
bool isShotted = false; //任务是否已触发
std::function<void()> timedTask; //定时任务
};
#pragma once
#include <graphics.h>
#include <vector>
class Atlas {
public:
void load(LPCTSTR path, int num); //加载图集
void addImage(const IMAGE& img); //加载单张
void clear(); //清空图集
public:
int getSize() const; //图集大小
IMAGE* getImage(int i); //返回图片
private:
std::vector<IMAGE> imgs;
};
#pragma once
#include <graphics.h>
#pragma comment(lib, "MSIMG32.LIB") //AlphaBlend
#pragma comment(lib, "WINMM.LIB") //mp3
struct Rect{
int x, y;
int w, h;
};
//裁剪img任意大小的图并显示在任意处
//src 裁剪
//dst 缩放
void putImageEx(IMAGE* img, const Rect* dst, const Rect* src = nullptr) {
Rect src_{ 0, 0, img->getwidth(), img->getheight() };
if (src)
src_ = *src;
//将(src_x, src_y), w, h 的图像 复制到 (dst_x, dst_y)处
AlphaBlend(GetImageHDC(GetWorkingImage()),
dst->x, dst->y, dst->w, dst->h,
GetImageHDC(img),
src_.x, src_.y, src_.w, src_.h,
{ AC_SRC_OVER, 0, 255, AC_SRC_ALPHA });
}
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- oldu.cn 版权所有 浙ICP备2024123271号-1
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务