能帮到你的话,就给个赞吧 😘
文件太多,仅更新 更新的内容
util.h
#pragma once
#include <graphics.h>
void flipImage(IMAGE* src, IMAGE* dst);
void putImageAlpha(int x, int y, IMAGE* img); //图像绘制(透明度)
util.cpp
#include "util.h"
#pragma comment(lib, "MSIMG32.LIB") //AlphaBlend
void flipImage(IMAGE* src, IMAGE* dst){
int height = src->getheight();
int width = src->getwidth();
Resize(dst, width, height);
auto srcPixels = GetImageBuffer(src);
auto dstPixels = GetImageBuffer(dst);
for (int h = 0; h < height; h++)
for (int w = 0; w < width; w++)
dstPixels[h * width + w] = srcPixels[h * width + width - 1 - w];
}
void putImageAlpha(int x, int y, IMAGE* img) {
int w = img->getwidth();
int h = img->getheight();
/*
AlphaBlend: Windows GDI+ API,用于图像混合。
GetImageHDC(nullptr), x, y, w, h:
GetImageHDC(nullptr):获取屏幕
x, y, w, h: 屏幕的位置,作为目标区域。(左上角坐标为x,y,宽为w,高为h)
GetImageHDC(img), 0, 0, w, h:
GetImageHDC(img):获取图像
0, 0, w, h: 整个图像,作为源区域。
{ AC_SRC_OVER,0,255, AC_SRC_ALPHA }: 将源图像以透明的方式覆盖到目标图像上,透明度由源图像的Alpha通道控制。
AC_SRC_OVER: 源图像覆盖目标图像
0,255: 参数,此处无作用
AC_SRC_ALPHA: 指定源图像的Alpha通道覆盖
图像的Alpha通道: 是图像的透明度通道,存储着每个像素的透明度信息
*/
AlphaBlend(GetImageHDC(nullptr), x, y, w, h, GetImageHDC(img), 0, 0, w, h, { AC_SRC_OVER,0,255, AC_SRC_ALPHA });
}
main
#include <Windows.h> //windows要放在graphics之前
#include <graphics.h>
#include "menuScene.h"
#include "gameScene.h"
#include "selectorScene.h"
#include "sceneManager.h"
#include "util.h"
#include "atlas.h"
#include <thread>
#include <chrono>
#pragma comment(lib, "Winmm.lib") //mciSendString
IMAGE imgMenuBackground;
IMAGE imgVs; //艺术字
IMAGE img1P; //文本
IMAGE img2P;
IMAGE img1PDesc; //描述
IMAGE img2PDesc;
IMAGE imgGraveStoneLeft; //向左墓碑
IMAGE imgGraveStoneRight;
IMAGE imgSelectorTip; //选择提示
IMAGE imgSelectorBackground;
IMAGE img1PSelectorButtonLeftIdle; //1P向左选择按钮默认
IMAGE img1PSelectorButtonRightIdle;
IMAGE img1PSelectorButtonLeftDown;
IMAGE img1PSelectorButtonRightDown; //1P向左选择按钮按下
IMAGE img2PSelectorButtonLeftIdle;
IMAGE img2PSelectorButtonRightIdle;
IMAGE img2PSelectorButtonLeftDown;
IMAGE img2PSelectorButtonRightDown;
IMAGE imgPeaShooterSelectorLeftBackground; //豌豆向左选择界面
IMAGE imgPeaShooterSelectorRightBackground;
IMAGE imgSunFlowerSelectorLeftBackground; //向日葵向左选择界面
IMAGE imgSunFlowerSelectorRightBackground;
IMAGE imgSky; //天空
IMAGE imgHills; //山脉
IMAGE imgLargePlatform; //平台
IMAGE imgSmallPlatform;
IMAGE img1PCursor;
IMAGE img2PCursor;
Atlas atlasPeaShooterIdleLeft; //豌豆向左
Atlas atlasPeaShooterIdleRight;
Atlas atlasPeaShooterRunLeft;
Atlas atlasPeaShooterRunRight;
Atlas atlasPeaShooterAttackExLeft; //豌豆向左特殊攻击
Atlas atlasPeaShooterAttackExRight;
Atlas atlasPeaShooterDieLeft; //向左死亡
Atlas atlasPeaShooterDieRight;
Atlas atlasSunFlowerIdleLeft; //向日葵
Atlas atlasSunFlowerIdleRight;
Atlas atlasSunFlowerRunLeft;
Atlas atlasSunFlowerRunRight;
Atlas atlasSunFlowerAttackExLeft;
Atlas atlasSunFlowerAttackExRight;
Atlas atlasSunFlowerDieLeft;
Atlas atlasSunFlowerDieRight;
IMAGE imgPea; //豌豆
Atlas atlasPeaBreak;
Atlas atlasSun;
Atlas atlasSunExplode; //太阳爆炸
Atlas atlasSunEX; //特殊动画
Atlas atlasSunEXExplode; //特殊爆炸
Atlas atlasSunText; //文本动画
Atlas atlasRunEffect; //奔跑特效
Atlas atlasJumpEffect;
Atlas atlasLandEffect;
IMAGE img1PWinner; //1P获胜文本
IMAGE img2PWinner;
IMAGE imgWinnerBar; //获胜背景
IMAGE imgPeaShooterAvatar; //豌豆头像
IMAGE imgSunFlowerAvatar; //向日葵头像
//场景与场景管理器互相引用
Scene* menuScene = new MenuScene;
Scene* gameScene = new GameScene;
Scene* selectorScene = new SelectorScene;
SceneManager sceneManager;
void flipAtlas(Atlas& src, Atlas& dst) {
dst.clear();
for (int i = 0; i < src.getSize(); i++) {
IMAGE img;
flipImage(src.getImage(i), &img);
dst.addImage(img);
}
}
void loadResources() {
//加载字体
//将 IPix.ttf" 加载到系统字体中,并将其设置为私有字体。
AddFontResourceEx(_T("resources/IPix.ttf"), FR_PRIVATE, nullptr);
//加载图片
loadimage(&imgVs, _T("resources/VS.png"));
loadimage(&img1P, _T("resources/1P.png"));
loadimage(&img2P, _T("resources/2P.png"));
loadimage(&img1PDesc, _T("resources/1P_desc.png"));
loadimage(&img2PDesc, _T("resources/2P_desc.png"));
loadimage(&imgGraveStoneRight, _T("resources/gravestone.png"));
flipImage(&imgGraveStoneRight, &imgGraveStoneLeft);
loadimage(&imgSelectorTip, _T("resources/selector_tip.png"));
loadimage(&imgSelectorBackground, _T("resources/selector_background.png"));
loadimage(&img1PSelectorButtonRightIdle, _T("resources/1P_selector_btn_idle.png"));
flipImage(&img1PSelectorButtonRightIdle, &img1PSelectorButtonLeftIdle);
loadimage(&img1PSelectorButtonRightDown, _T("resources/1P_selector_btn_down.png"));
flipImage(&img1PSelectorButtonRightDown, &img1PSelectorButtonLeftDown);
loadimage(&img2PSelectorButtonRightIdle, _T("resources/2P_selector_btn_idle.png"));
flipImage(&img2PSelectorButtonRightIdle, &img2PSelectorButtonLeftIdle);
loadimage(&img2PSelectorButtonRightDown, _T("resources/2P_selector_btn_down.png"));
flipImage(&img2PSelectorButtonRightDown, &img2PSelectorButtonLeftDown);
loadimage(&imgPeaShooterSelectorRightBackground, _T("resources/peashooter_selector_background.png"));
flipImage(&imgPeaShooterSelectorRightBackground, &imgPeaShooterSelectorLeftBackground);
loadimage(&imgSunFlowerSelectorRightBackground, _T("resources/sunflower_selector_background.png"));
flipImage(&imgSunFlowerSelectorRightBackground, &imgSunFlowerSelectorLeftBackground);
loadimage(&imgSky, _T("resources/sky.png"));
loadimage(&imgHills, _T("resources/hills.png"));
loadimage(&imgLargePlatform, _T("resources/platform_large.png"));
loadimage(&imgSmallPlatform, _T("resources/platform_small.png"));
loadimage(&img1PCursor, _T("resources/1P_cursor.png"));
loadimage(&img2PCursor, _T("resources/2P_cursor.png"));
atlasPeaShooterIdleRight.loadImages(_T("resources/peashooter_idle_%d.png"), 9);
flipAtlas(atlasPeaShooterIdleRight, atlasPeaShooterIdleLeft);
atlasPeaShooterRunRight.loadImages(_T("resources/peashooter_run_%d.png"), 5);
flipAtlas(atlasPeaShooterRunRight, atlasPeaShooterRunLeft);
atlasPeaShooterAttackExRight.loadImages(_T("resources/peashooter_attack_ex_%d.png"), 3);
flipAtlas(atlasPeaShooterAttackExRight, atlasPeaShooterAttackExLeft);
atlasPeaShooterDieRight.loadImages(_T("resources/peashooter_die_%d.png"), 4);
flipAtlas(atlasPeaShooterDieRight, atlasPeaShooterDieLeft);
atlasSunFlowerIdleRight.loadImages(_T("resources/sunflower_idle_%d.png"), 8);
flipAtlas(atlasSunFlowerIdleRight, atlasSunFlowerIdleLeft);
atlasSunFlowerRunRight.loadImages(_T("resources/sunflower_run_%d.png"), 5);
flipAtlas(atlasSunFlowerRunRight, atlasSunFlowerRunLeft);
atlasSunFlowerAttackExRight.loadImages(_T("resources/sunflower_attack_ex_%d.png"), 9);
flipAtlas(atlasSunFlowerAttackExRight, atlasSunFlowerAttackExLeft);
atlasSunFlowerDieRight.loadImages(_T("resources/sunflower_die_%d.png"), 2);
flipAtlas(atlasSunFlowerDieRight, atlasSunFlowerDieLeft);
loadimage(&imgPea, _T("resources/pea.png"));
atlasSunFlowerIdleRight.loadImages(_T("resources/pea_break_%d.png"), 3);
atlasSunFlowerIdleRight.loadImages(_T("resources/sun_%d.png"), 5);
atlasSunFlowerIdleRight.loadImages(_T("resources/sun_explode_%d.png"), 5);
atlasSunFlowerIdleRight.loadImages(_T("resources/sun_ex_%d.png"), 5);
atlasSunFlowerIdleRight.loadImages(_T("resources/sun_ex_explode_%d.png"), 5);
atlasSunFlowerIdleRight.loadImages(_T("resources/sun_text_%d.png"), 6);
atlasRunEffect.loadImages(_T("resources/run_effect_%d.png"), 4);
atlasJumpEffect.loadImages(_T("resources/jump_effect_%d.png"), 5);
atlasLandEffect.loadImages(_T("resources/land_effect_%d.png"), 2);
loadimage(&img1PWinner, _T("resources/1P_winner.png"));
loadimage(&img2PWinner, _T("resources/2P_winner.png"));
loadimage(&imgWinnerBar, _T("resources/winnner_bar.png"));
loadimage(&imgPeaShooterAvatar, _T("resources/avatar_peashooter.png"));
loadimage(&imgSunFlowerAvatar, _T("resources/avatar_sunflower.png"));
//加载音乐
mciSendString(_T("open resources/bgm_game.mp3 alias bgmGame"), nullptr, 0, nullptr);
mciSendString(_T("open resources/bgm_menu.mp3 alias bgmMenu"), nullptr, 0, nullptr);
mciSendString(_T("open resources/pea_break_1.mp3 alias peaBreak1"), nullptr, 0, nullptr);
mciSendString(_T("open resources/pea_break_2.mp3 alias peaBreak2"), nullptr, 0, nullptr);
mciSendString(_T("open resources/pea_break_3.mp3 alias peaBreak3"), nullptr, 0, nullptr);
mciSendString(_T("open resources/pea_shoot_1.mp3 alias peaShoot1"), nullptr, 0, nullptr);
mciSendString(_T("open resources/pea_shoot_2.mp3 alias peaShoot2"), nullptr, 0, nullptr);
mciSendString(_T("open resources/pea_shoot_ex.mp3 alias peaShootEx"), nullptr, 0, nullptr);
mciSendString(_T("open resources/sun_explode.mp3 alias sunExplode"), nullptr, 0, nullptr);
mciSendString(_T("open resources/sun_explode_ex.mp3 alias sunExplodeEx"), nullptr, 0, nullptr);
mciSendString(_T("open resources/sun_text.mp3 alias sunText"), nullptr, 0, nullptr);
mciSendString(_T("open resources/ui_confirm.wav alias uiConfirm"), nullptr, 0, nullptr);
mciSendString(_T("open resources/ui_switch.wav alias uiSwitch"), nullptr, 0, nullptr);
mciSendString(_T("open resources/ui_win.wav alias uiWin"), nullptr, 0, nullptr);
}
int main() {
loadResources();
sceneManager.setCurrentScene(menuScene); //初始化管理器
ExMessage msg;
const int FPS = 1000 / 1;
initgraph(700, 600, EW_SHOWCONSOLE);
BeginBatchDraw();
while (1) {
//auto startTime = GetTickCount64();
//读消息
peekmessage(&msg);
//处理消息
sceneManager.onInput(msg);
//更新数据
sceneManager.onUpdate();
//渲染
cleardevice();
sceneManager.onDraw();
FlushBatchDraw();
//hertz
/*auto excutionTime = GetTickCount64() - startTime;
if (excutionTime < FPS)
Sleep(FPS - excutionTime);*/
//Sleep(1000);
std::this_thread::sleep_for(std::chrono::microseconds(100));
}
EndBatchDraw();
//释放资源
delete menuScene;
delete gameScene;
}
animation.h
#pragma once
#include <graphics.h>
#include "atlas.h"
#include <functional>
class Animation {
public:
void update(int playTime); //更新动画数据
void draw(int x, int y); //渲染
public:
void reset();
void setAtals(Atlas* atlas);
void setIsLoop(bool isLoop);
void setInterval(int ms);
void setCallback(const std::function<void()>& cb);
public:
int getFrameIndex();
IMAGE* getFrame();
bool checkFinish();
private:
int time = 0; //计时器
int interval; //帧间隔
int index = 0; //帧索引
Atlas* atlas;
bool isLoop = true;
std::function<void()> callback;
};
animation.cpp
#include "animation.h"
#include "util.h"
//增加动画播放的时间
void Animation::update(int playTime){
if (time > interval) {
time = 0;
index++;
if (index == atlas->getSize()) {
index = isLoop ? 0 : atlas->getSize() - 1;
if (!isLoop && callback)
callback();
}
}
time += playTime;
}
void Animation::draw(int x, int y){
putImageAlpha(x, y, atlas->getImage(index));
}
void Animation::reset(){
time = 0;
index = 0;
}
void Animation::setAtals(Atlas* atlas){
this->atlas = atlas;
}
void Animation::setIsLoop(bool isLoop){
this->isLoop = isLoop;
}
void Animation::setInterval(int ms){
interval = ms;
}
void Animation::setCallback(const std::function<void()>& cb){
callback = cb;
}
int Animation::getFrameIndex(){
return index;
}
IMAGE* Animation::getFrame(){
return atlas->getImage(index);
}
bool Animation::checkFinish(){
if (isLoop)
return false;
return index == atlas->getSize() - 1;
}