软件:Codeblocks 2017,2020
插件:sfml
代码:
main.cpp
#include "ut.hpp"
#include <pthread.h>
#include <vector>
#include <string>
#include <windows.h>
#include <iostream>
//BUG:最后的BOX现不出来啊!!!
using namespace std;
using namespace sf;
using namespace ut;
extern ut::Must MustDefine;
//疑问:为什么extern不可以导出静态的变量??So why??
typedef sf::RenderWindow rwin;
typedef string Token;//如果是字符串,value为处理后的值
struct GDStruct{
vector<Token> tokens;
};
pthread_t checkingevent;
sf::Font sansation;
sf::Mutex mutex;
void prepareData();
GDStruct readStruct(string data);
bool toBool(string data);
int getDataByName(vector<Data> * ds,string name);
vector<string> getGameDataStrings(string all);
vector<vector<OneString>> readOneStringData(vector<GDStruct> odata,vector<float> * wtt);
int main(){
srand(time(0));
rwin * window = new sf::RenderWindow(sf::VideoMode(800,600),"Undertale",sf::Style::Close | sf::Style::Titlebar);
MustDefine.winsize = {800,600};
//prepareData();
int error;
vector<Data> data = ut::readData("+1.data",&error);
int fontSansationIndex = getDataByName(&data,"font:sansation");
int startPageIndex = getDataByName(&data,"game:startPage");
if(error != 0 || fontSansationIndex == -1){
MessageBox(window->getSystemHandle(),"Datas have wrong!","Undertale has wrong!",MB_OK | MB_TOPMOST | MB_ICONERROR);
return -1;
}
if(!sansation.loadFromMemory(data[fontSansationIndex].data.data(),data[fontSansationIndex].data.size()))return -1;
string s = (char *)data[startPageIndex].data.data();
vector<string> gds = getGameDataStrings(s);
vector<GDStruct> structOfGD;
vector<float> waitTime;
cout << "here" << endl;
int i = 0;
for(unsigned int z = 0;z < gds.size();z++){
structOfGD.push_back(readStruct(gds[z]));
}
vector<vector<OneString>> dtaBox = readOneStringData(structOfGD,&waitTime);
ut::StringBox * box = new ut::StringBox(dtaBox[i],{false,sf::Color::White,700});
sf::Sprite sp;
sp.setPosition(0,0);
sf::Clock clk,textureClock;
sf::Time textureTime = sf::seconds(0),time2 = sf::seconds(0),ep;
textureClock.restart();
cout << "oh" << endl;
while(window->isOpen()){
sf::Event event;
if(window->pollEvent(event)){
if(event.type == sf::Event::Closed)window->close();
else if(event.type == sf::Event::KeyPressed){
if(event.key.code == sf::Keyboard::Escape){
}
}
}
ep = textureClock.restart();
textureTime += ep;
time2 += ep;
if(time2.asSeconds() >= waitTime[i]){
i++;
textureTime = sf::seconds(0);
delete box;
box = new ut::StringBox(dtaBox[i],{true,sf::Color::White,700});
}
window->clear();
sp.setTexture((box->toTexture(textureTime))->getTexture());
window->draw(sp);
window->display();
float f = clk.restart().asSeconds();
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),{0,0});
cout << 1/f << " " << endl;
}
delete window;
return 0;
}
void prepareData(){
if(!sansation.loadFromFile("+0.data"))exit(-1);
}
bool toBool(string data){//receive 0,1,true,false
if(data.compare("1") == 0 || data.compare("true") == 0)return true;
else return false;
}
GDStruct readStruct(string data){
bool inString = false,inReflect = false,inToken = false;
vector<Token> tokens;
Token temp = "";
for(unsigned int i = 0;i < data.size();i++){
if(data[i] == ' ' && inToken && !inString){
inToken = false;
tokens.push_back(temp);
temp = "";
}else if(data[i] == '\"'){
inToken = true;
if(!inReflect)inString = !inString;
}else if(data[i] == '\\'){
inToken = true;
inReflect = true;
}else if(data[i] != ' ' || inString){
inToken = true;
if(inReflect){
switch(data[i]){
case ' ':
break;
case 'n':
temp += '\n';
break;
case 't':
temp += '\t';
break;
case '\'':
temp += '\'';
break;
case '"':
temp += '\"';
break;
case 'v':
temp += '\v';
break;
default:
temp += "{errorInTheReflectCase}";
break;
}
}else temp += data[i];
}
}
return {tokens};
}
int getDataByName(vector<Data> * ds,string name){
for(unsigned int i = 0;i < ds->size();i++){
if((*ds)[i].name.compare(name) == 0)return i;
}
return -1;
}
vector<string> getGameDataStrings(string all){
string temp = "";
vector<string> data;
for(unsigned int i = 0;i < all.size();i++){
if(all[i] == '\n'){
data.push_back(temp);
temp = "";
}else{
temp += all[i];
}
}
return data;
}
vector<vector<OneString>> readOneStringData(vector<GDStruct> odata,vector<float> * waitT){
bool addData = false,setting = false,next = false;
vector<OneString> temp1;
vector<vector<OneString>> rt;
waitT->clear();
for(unsigned int x = 0;x < odata.size();x++){
OneString temp = OneString("",sf::Color::Transparent,0,NULL,0);
for(unsigned int y = 0;y < odata[x].tokens.size();y++){
switch(y){
case 0:
if(odata[x].tokens[y].compare("reg") == 0)break;
else if(odata[x].tokens[y].compare("add") == 0){
addData = true;
}else if(odata[x].tokens[y].compare("set") == 0){
setting = true;
}else if(odata[x].tokens[y].compare("nex") == 0){
rt.push_back(temp1);
temp1.clear();
next = true;
}
break;
case 1:
if(addData){
temp.str = odata[x].tokens[y];
}else if(setting){
waitT->push_back((float)atof(odata[x].tokens[y].c_str()));
}
break;
case 2:
if(addData){
if(odata[x].tokens[y].compare("black") == 0){
temp.color = sf::Color::Black;
}else if(odata[x].tokens[y].compare("green") == 0){
temp.color = sf::Color::Green;
}else if(odata[x].tokens[y].compare("white") == 0){
temp.color = sf::Color::White;
}else if(odata[x].tokens[y].compare("transparent") == 0){
temp.color = sf::Color::Transparent;
}else if(odata[x].tokens[y].compare("cyan") == 0){
temp.color = sf::Color::Cyan;
}else if(odata[x].tokens[y].compare("magenta") == 0){
temp.color = sf::Color::Magenta;
}else if(odata[x].tokens[y].compare("blue") == 0){
temp.color = sf::Color::Blue;
}else if(odata[x].tokens[y].compare("red") == 0){
temp.color = sf::Color::Red;
}else if(odata[x].tokens[y].compare("yellow") == 0){
temp.color = sf::Color::Yellow;
}else{
temp.color = sf::Color::White;
}
}
break;
case 3:
if(addData){
temp.size = (unsigned int)atoi(odata[x].tokens[y].c_str());
}
break;
case 4:
if(addData){
if(odata[x].tokens[y].compare("sansation") == 0){
temp.font = &sansation;
}else{
temp.font = &sansation;
}
}
break;
case 5:
if(addData){
temp.keepSeconds = (float)atof(odata[x].tokens[y].c_str());
}
break;
case 6:
if(addData){
temp.exPosition = toBool(odata[x].tokens[y]);
}
break;
case 7:
if(addData){
float x2 = (float)atof(odata[x].tokens[y].c_str()),
y2 = (float)atof(odata[x].tokens[y+1].c_str());
temp.position = {x2,y2};
}
break;
case 8:
if(!addData){//The code is right!!!
}
break;
case 9:
if(addData){
temp.printPerChar = toBool(odata[x].tokens[y]);
}
break;
case 10:
if(addData){
temp.percharSeconds = (float)atof(odata[x].tokens[y].c_str());
}
break;
case 11:
if(addData){
temp.textShake = toBool(odata[x].tokens[y]);
}
break;
case 12:
if(addData){
temp.bold = toBool(odata[x].tokens[y]);
}
break;
case 13:
if(addData){
temp.italic = toBool(odata[x].tokens[y]);
}
break;
default:
break;
}
if(next){
break;
}
}
if(next){
next = false;
continue;
}
temp1.push_back(temp);
addData = setting = false;
}
return rt;
}
ut.hpp
#ifndef UT_HPP_LOCK
#define UT_HPP_LOCK
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <SFML/System.hpp>
#include <SFML/Network.hpp>
#include <string>
#include <vector>
#include <iostream>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <windows.h>
using namespace sf;
using namespace std;
namespace ut{
typedef float fl;
typedef sf::Vector2f vec2f;
typedef sf::Texture tex;
typedef sf::Sprite img;
typedef unsigned int uint;
class ImageUpdate{
public:
///@summary:更新图片
///@return 无
///@param image 指向图片的指针
///@param arg 更新参数
///@param frame 帧数ps:控制在每秒64帧以下
virtual void updateImage(sf::Sprite * image,int arg,int frame);
};
class MonsterInfo{
public:
uint round;
};
///~~关键帧
class ImportantFrame{
public:
///关键帧的图片
tex * texture;
///关键帧的持续时间
int keepTime;
};
class Animation{
public:
///@summary 图片信息
std::vector<ImportantFrame> texs;
int index;
///构造
Animation();
///@summary 更新图片
///@return void
///@param img1 待更新的图片
void update(img * img1);
///@summary 重设顺序
///@return void
///@param none
void resetIndex();
};
typedef Animation cart;//cartoon
class Animator{
public:
///@summary:更新自己的图片
///@return none
///@param none
virtual void updateSelfImage();
///@summary 组合动画获得图片
///@return cart 组合完毕的动画
///@param arg0 参数一
///@param arg1 参数二
virtual cart getAnimation(int arg0,std::string arg1);
};
class Monster : public Animator , public Animation{
public:
};
struct OneString{
std::string str;//必设
sf::Color color;//必设
uint size;//必设
bool textShake;
bool bold;
bool italic;
bool exPosition;
vec2f position;
sf::Font * font;//必设
float keepSeconds;//必设,实际上为展现前的等待时间,非持续时间
bool printPerChar;
float percharSeconds;
OneString(std::string value,sf::Color textColor,uint textSize,sf::Font * textFont,float waitTimeSec,
bool exPos = false,vec2f pos = {0,0},bool printPc = false,float pcsec = 0,
bool textShaking = false,bool textbold = false,bool textItalic = false);
OneString();
};
struct StringBoxFormat{
public:
bool ex;
sf::Color exColor;
float maxPixel;
};
class StringBox{
public:
sf::RenderTexture * data;
StringBoxFormat fmt;
std::vector<OneString> datas;
sf::RenderTexture * toTexture(sf::Time texTime);//Remember to free the data
float getFinishedTextureSeconds();
StringBox(std::vector<OneString> data2,StringBoxFormat format);
private:
fl finishedDrawingTime;
};
class Must{
public:
sf::Vector2i winsize;
};
class Data{
public:
string name;
vector<BYTE> data;
};
vector<Data> readData(string fname,int * error);
}
#endif
ut.cpp
#include "ut.hpp"
using namespace ut;
Must MustDefine;
void ut::Animation::resetIndex(){
this->index = 0;
}
void ut::Animation::update(img * img1){
if(this->index+1 >= (int)this->texs.size())this->index = 0;
else (this->index)++;
img1->setTexture(*((this->texs[this->index]).texture));
}
ut::StringBox::StringBox(std::vector<OneString> data2,StringBoxFormat format){
this->datas = data2;
this->finishedDrawingTime = -1;
fmt = format;
data = NULL;
}
float ut::StringBox::getFinishedTextureSeconds(){
return this->finishedDrawingTime;
}
ut::OneString::OneString(){
}
sf::RenderTexture * ut::StringBox::toTexture(sf::Time texTime){
if(this->data != NULL){delete data;data = NULL;}
data = new sf::RenderTexture();
if(!data->create(MustDefine.winsize.x,MustDefine.winsize.y)){delete data;data = NULL;return NULL;}
data->clear(sf::Color::Transparent);
vec2f extensionPosition = {0,0};
std::vector<sf::Text *> txts;
fl maxY = 0;
fl maxX0 = 0,maxY0 = 0;
bool finisheDrawing = false;
fl orignx = 0;
fl nowSec = texTime.asSeconds(),allsec = 0;
sf::VertexArray * array0 = new sf::VertexArray(sf::Quads,4);
(*array0)[0].position = {0,0};
for(int i = 0;i < 4;i++){
if(fmt.ex)(*array0)[i].color = fmt.exColor;
else (*array0)[i].color = sf::Color::Transparent;
}
for(uint i = 0;i < this->datas.size();i++){
OneString tar = this->datas[i];
allsec += tar.keepSeconds;
if(nowSec < allsec)break;
string useStr = tar.str;
if(tar.printPerChar){
useStr = "";
for(uint p = 0;p < tar.str.size();p++){
allsec += tar.percharSeconds;
if(nowSec < allsec){
finisheDrawing = false;
break;
}
useStr += tar.str[p];
if(p == tar.str.size()-1){
if(i == datas.size()-1){
finisheDrawing = true;
}
}
}
}
sf::Text * text = new sf::Text(useStr,*(tar.font),tar.size);
if(tar.exPosition){
extensionPosition = tar.position;
orignx = tar.position.x;
}
text->setPosition(extensionPosition);
vec2f edpos = extensionPosition;
text->setOutlineColor(tar.color);
text->setFillColor(tar.color);
text->setStyle((tar.bold?sf::Text::Bold:0)|(tar.italic?sf::Text::Italic:0));
sf::FloatRect rct = text->getGlobalBounds();
fl x = rct.width;
extensionPosition.x += x;
if(extensionPosition.x >= fmt.maxPixel){
extensionPosition.y += maxY;
extensionPosition.x = orignx;
maxY = 0;
}
if(tar.textShake){
int ux = 0,uy = 0;
ux = (rand()%512>256?1:-1)*(rand()%5);
uy = (rand()%512>256?1:-1)*(rand()%5);
edpos.x += ux;
edpos.y += uy;
text->setPosition(edpos);
}
txts.push_back(text);
sf::FloatRect rct2v = text->getGlobalBounds();
if((text->getPosition().y+rct2v.height) > (maxY0)){
maxY0 = rct2v.top + rct2v.height;
}
if(i == datas.size()-1 ){
maxX0 = rct2v.left + rct2v.width + 4;
}else if((nowSec < (allsec + datas[i+1].keepSeconds))){//不得不这样,如果i == txts.szie()-1,那么....(调试故障!!!)
maxX0 = rct2v.left + rct2v.width + 4;
}
}
if(finisheDrawing){
finishedDrawingTime = texTime.asSeconds() - allsec;
}
maxY0 += 4;
(*array0)[1].position = {0,maxY0};
(*array0)[2].position = {maxX0,maxY0};
(*array0)[3].position = {maxX0,0};
data->draw(*array0);
for(uint i = 0;i < txts.size();i++){
data->draw(*txts[i]);
}
data->display();
for(uint i = 0;i < txts.size();i++){
delete txts[i];
}
delete array0;
return data;
}
ut::OneString::OneString(std::string value,sf::Color textColor,uint textSize,sf::Font * textFont,float keepTimeSec,
bool exPos,vec2f pos,bool printPc,float pcsec,bool textShaking,bool textbold,bool textItalic){
this->str = value;
this->color = textColor;
this->size = textSize;
this->font = textFont;
this->keepSeconds = keepTimeSec;
this->exPosition = exPos;
this->position = pos;
this->printPerChar = printPc;
this->percharSeconds = pcsec;
this->textShake = textShaking;
this->bold = textbold;
this->italic = textItalic;
}
vector<Data> ut::readData(string fname,int * error){
char name[] = {'N','A','M','E'};
char data[] = {'D','A','T','A'};
char tok[4];
FILE * f = NULL;
*error = 0;
vector<Data> dta = {};
if((f = fopen(fname.c_str(),"rb")) == NULL){
*error = 1;
return {};
}
unsigned int sz = 0;
while(!feof(f)){
Data d;
unsigned int r = fread(tok,sizeof(char),4,f);
//cout << "TOCK:" << tok << endl;
if(r < 4){break;}
for(int i = 0;i < 4;i++){
if(tok[i] != name[i]){
*error = 1;
return dta;
}
}
fread(&sz,sizeof(unsigned int),1,f);
string n = "";
n.resize(sz);
fread((void *)n.c_str(),sizeof(char),sz,f);
//cout << "FILE NAME:" << n << endl;
d.name = n;
tok[0] = tok[1] = tok[2] = tok[3] = '\0';
fread(tok,sizeof(char),4,f);
for(int i = 0;i < 4;i++){
if(tok[i] != data[i]){
*error = 3;
return dta;
}
}
fread(&sz,sizeof(unsigned int),1,f);
for(unsigned int i = 0;i < sz;i++){
BYTE b = 0;
fread(&b,sizeof(BYTE),1,f);
d.data.push_back(b);
}
tok[0] = tok[1] = tok[2] = tok[3] = '\0';
dta.push_back(d);
}
fclose(f);
*error = 0;
return dta;
}
请提供最简明的代码,显示你的问题出现在什么情况下,什么输入会导致问题。
不用了,我把cb重新装了一遍,然后又重新编译了sfml,现在好了