最近在用easyx做小游戏的时候需要滚动文本来查看历史消息,果断csdn,github,baidu一番,无果,但这点问题怎么能拦住我们大学牲!索性自己搓一个自己能用的就行。
首先,我们需要创建一个绘图窗口并且指定输出文本区域,利用initgraph()能很轻松达成这点:
int main()
{
initgraph(720, 800, 1);//分别为绘制窗口的宽,高,是否显示控制台窗口,第三个参数为非零即显示
setbkcolor(WHITE);//设置背景颜色为白色
cleardevice();//刷新画布(用先前设置的背景颜色予以填充画布)
setlinecolor(BLACK);//设置画线颜色
line(0, 500, 720, 500);//随便拉条线设置文字输出区域
while(1);//防止窗口一闪而过
return 0;
}
然后我们需要输出文本,虽然easyx已经自带了outtextxy(),drawtext(),等文字输出函数,但是每次输出都要指定坐标,并且无法删除上一次的输出,会造成字幕重叠,很是麻烦,所以,我们干脆自己构造一个输出函数:
int outputnum=0;//设置一个输出语句y坐标全局变量
int interfacex=720;//设置窗口宽度
int interfacey=800;//设置窗口高度
void display(string text1, int color)//输出,参数分别为待输出语句和颜色
{
const char *text = text1.c_str();
if (outputnum >= 500)//如果当前输出语句已经占满画布,删除当前画布所有语句
{
outputnum = 0;
clearrectangle(-1, -1, interfacex, 500);
setfillcolor(WHITE);
fillrectangle(-1, -1, interfacex, 500);
}
settextstyle(18, 0, "仿宋");
settextcolor(color);//输出颜色
outtextxy(8, outputnum, text);//输出语句
outputnum += 22;
}
很好!我们已经有了一个完美(?)的文本输出函数!然后呢,我们回到最初的目的,滚动输出文本,现在只能文本输出到一定数量全部消失然后重新输出,有问题,大问题。
如果我们需要滚动输出历史文本,那么第一肯定是要储存历史文本,本来是想用链表存取历史语句的,但是后来发现有点杀鸡用牛刀了,一个全局string字符组就能解决:
int num=0;//字符组最大下标控制
string history0[]={""};//储存历史文本
int history1[]=0;//储存历史文本颜色
void savetxt(string text, int color)
{
const char *text1 = text.c_str();
if (strlen(text1) >= 78) {//如果语句长度超过当前画布interfacex
string text3 = text.substr(78);//擦去前段
string text2 = text.erase(78, strlen(text1) - 78);//擦去后段
if (num >= 72){
for (int i = 0; i < 72; i++){//如果字符组装满了,挤掉最前面一条
history0[i] = history0[i + 1];
history1[i] = history1[i + 1];
}
history0[71] = text2;
history1[71] = color;
}
else {
history0[num] = text2;
history1[num] = color;
num++;//每储存一条,数组下标加1
}
savetxt(text3, color);
}
else{
if (num >= 72){
for (int i = 0; i < 72; i++){
history0[i] = history0[i + 1];
history1[i] = history1[i + 1];
}
history0[71] = text;
history1[71] = color;
}
else{
history0[num] = text;
history1[num] = color;
num++;
}
}
}
很好!我们已经完成了至关重要的一步!储存每一句输出的文本!,现在要做的就是输出它,我个人是当前屏幕输出23排最合适,有需要更改display的outputnum上限即可,然后用一个for循环控制输出这23句话:
int minhis = 0;
int maxhis = minhis + 23;
void output()
{
int numhis = 0;
while (1)
{
if (num > numhis&&num > 23)//只有在文本大于23句,且有新文本存入的情况下才控制for循环输出下移一位
{
numhis = num;
maxhis++;
minhis++;
//if (num == 72)num = 73;
}
BeginBatchDraw();
maxhis = minhis + 23;
for (int j = minhis; j < maxhis; j++)
display(history0[j], history1[j]);
EndBatchDraw();
}
}
最后,我们需要用用户输入来控制输出文本的前滚或回滚,那么,再构造一个scrolltxt()函数并把输出函数也集成进去吧:
void scrolltxt(){
ExMessage msg;
while (1){
msg = getmessage(EM_MOUSE);
if (msg.message == WM_MOUSEWHEEL && num > 24){
if (msg.x > 0 && msg.x < 720 && msg.y < 505 && msg.y > 0 && msg.wheel > 0){
minhis--;
if (minhis <= 0) minhis = 0;
//cout << "maxhis: " << maxhis << " " << "minhis: " << minhis << endl;
}
else if (msg.x > 0 && msg.x < 720 && msg.y < 505 && msg.y > 0 && msg.wheel < 0){
minhis++;
if (minhis >= 49) minhis = 49;
if (maxhis >= num) minhis = num - 23;
//cout << num << endl;
//cout << "maxhis: " << maxhis << " " << "minhis: " << minhis << endl;
}
}
if (num > numhis&&num > 23)
{
numhis = num;
maxhis++;
minhis++;
if (num == 72)num = 73;
}
BeginBatchDraw();
maxhis = minhis + 23;
for (int j = minhis; j < maxhis; j++)
display(history0[j], history1[j]);
EndBatchDraw();
}
}
但这样的话我们无法实时输入文本,所以,为了贴合需求,我是把输出与更新文本分成了两个线程并发执行的,在这里我们只完成滚动输出的效果,其余例如把scrolltxt抽象一个控件类型等在这里就不赘述了。我个人的代码如下:
#include "head.h"
#include <easyx.h>
#include <iostream>
using namespace std;
int interfacex = 720;
int interfacey = 650;
int outputnum = 0;
int num=0;
int minhis = 0;
int maxhis = minhis + 23;
string history0[72] = {""};
int history1[72] = {0};
void display(string text1, int color)
{
const char *text = text1.c_str();
if (outputnum >= 500)
{
outputnum = 0;
clearrectangle(-1, -1, interfacex, 500);
setfillcolor(WHITE);
fillrectangle(-1, -1, interfacex, 500);
}
settextstyle(18, 0, "仿宋");
settextcolor(color);
outtextxy(8, outputnum, text);
outputnum += 22;
}
void savetxt(string text, int color)
{
const char *text1 = text.c_str();
if (strlen(text1) >= 78) {//如果字符长度超过当前画布interfacex
string text3 = text.substr(78);//擦去前段
string text2 = text.erase(78, strlen(text1) - 78);//擦去后段
if (num >= 72)
{
for (int i = 0; i < 72; i++)
{
history0[i] = history0[i + 1];
history1[i] = history1[i + 1];
}
history0[71] = text2;
history1[71] = color;
}
else {
history0[num] = text2;
history1[num] = color;
num++;
}
savetxt(text3, color);
}
else
{
if (num >= 72)
{
for (int i = 0; i < 72; i++)
{
history0[i] = history0[i + 1];
history1[i] = history1[i + 1];
}
history0[71] = text;
history1[71] = color;
}
else
{
history0[num] = text;
history1[num] = color;
num++;
}
}
}
void shuchu()
{
int numhis=0;
while (1)
{
if (num > numhis&&num > 23)
{
numhis = num;
maxhis++;
minhis++;
if (num == 72)num = 73;
}
BeginBatchDraw();
maxhis = minhis + 23;
for (int j = minhis; j < maxhis; j++)
display(history0[j], history1[j]);
EndBatchDraw();
}
}
void scrolltxt()
{
ExMessage msg;
while (1)
{
msg = getmessage(EM_MOUSE);
if (msg.message == WM_MOUSEWHEEL&&num>24)
{
if (msg.x > 0 && msg.x < 720 && msg.y < 505 && msg.y > 0 && msg.wheel > 0)
{
minhis--;
if (minhis <=0 ) minhis = 0;
cout << "maxhis: " << maxhis << " " << "minhis: " << minhis << endl;
}
else if (msg.x > 0 && msg.x < 720 && msg.y < 505 && msg.y > 0 && msg.wheel < 0)
{
minhis++;
if (minhis >= 49) minhis = 49;
if (maxhis >= num) minhis = num-23;
cout << num << endl;
cout << "maxhis: " << maxhis << " " << "minhis: " << minhis << endl;
}
}
}
}
int main()
{
initgraph(720,800,1);
setbkcolor(WHITE);
cleardevice();
setlinecolor(BLACK);
line(0, 500, 720, 500);
CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)shuchu,NULL,NULL,NULL);
for (int i = 0;i < 40; i++)
{
string str = to_string(i);
savetxt(str, RED);
Sleep(10);
}
scrolltxt();
}
以上。