Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ DOS ASCII动画滞后,无恒定输入,Turbo C编译_C++_Ascii_Render_Lag_Turbo C++ - Fatal编程技术网

C++ DOS ASCII动画滞后,无恒定输入,Turbo C编译

C++ DOS ASCII动画滞后,无恒定输入,Turbo C编译,c++,ascii,render,lag,turbo-c++,C++,Ascii,Render,Lag,Turbo C++,这是过去的一件怪事 我正在为命令提示符编写一个ASCII Pong游戏(Yes Yes oldschool),并直接写入视频内存(Add.0xB8000000),因此我知道我正在快速渲染(与gotoxy和printf渲染相反) 我的代码工作正常,代码在Turbo C++ V1.01下编译得很好,但是动画滞后了…等一下,等一下,有一个洞!在我的超高速增压涡轮增压戴尔核心2二人组下,这似乎是合乎逻辑的,但当我按住键盘上的一个键时,动画变得平滑,就像一个新编译的婴儿的底部一样 我想这可能是因为我通过重

这是过去的一件怪事

我正在为命令提示符编写一个ASCII Pong游戏(Yes Yes oldschool),并直接写入视频内存(Add.0xB8000000),因此我知道我正在快速渲染(与gotoxy和printf渲染相反)

<>我的代码工作正常,代码在Turbo C++ V1.01下编译得很好,但是动画滞后了…等一下,等一下,有一个洞!在我的超高速增压涡轮增压戴尔核心2二人组下,这似乎是合乎逻辑的,但当我按住键盘上的一个键时,动画变得平滑,就像一个新编译的婴儿的底部一样

我想这可能是因为我通过重载键盘缓冲区(wtf真的吗?来吧…)使计算机速度变慢了,但随后我迅速调整并尝试编译DJGPP和Tiny C编译器,以测试结果是否相同。在Tiny C编译器上,我发现我无法编译“远”指针类型。。。仍然困惑于这一点,但我能够编译的DJGPP和它的动画运行顺利

我想编译这个,并让它工作在Turbo C++中,但是这个问题困扰了我3天,没有解决。有人知道为什么Turbo C++常量调用我的渲染方法(下面的代码)会在命令提示符中滞后,但是DJGPP不会?我不知道我是否编译为debug,我甚至不知道如何检查我是否编译为debug。我确实将代码转换为ASM,我在源代码的标题处看到了调试数据的内容,所以我不知道

任何和所有的意见和帮助将不胜感激

下面是我遇到的一个快速示例,编译起来很简单,请查看:

#include<stdio.h>
#include<conio.h>
#include<dos.h>
#include<time.h>

#define bX 80
#define bY 24
#define halfX bX/2
#define halfY bY/2
#define resolution bX*bY

#define LEFT 1
#define RIGHT 2

void GameLoop();
void render();
void clearBoard();
void printBoard();
void ballLogic();

typedef struct {
 int x, y;
}vertex;

vertex vertexWith(int x, int y) {
 vertex retVal;
 retVal.x = x;
 retVal.y = y;
 return retVal;
}

vertex vertexFrom(vertex from) {
 vertex retVal;
 retVal.x = from.x;
 retVal.y = from.y;
 return retVal;
}

int direction;

char far *Screen_base;
char *board;
vertex ballPos;

void main() {
 Screen_base = (char far*)0xB8000000;
 ballPos = vertexWith(halfX, halfY);
 direction = LEFT;
 board = (char *)malloc(resolution*sizeof(char));
 GameLoop();
}

void GameLoop() {
 char input;

 clrscr();
 clearBoard();
 do {
  if(kbhit())
   input = getch();
  render();
  ballLogic();

  delay(50);
 }while(input != 'p');
 clrscr();
}

void render() {
 clearBoard();

 board[ballPos.y*bX+ballPos.x] = 'X';

 printBoard();
}

void clearBoard() {
 int d;
 for(d=0;d<resolution;d++)
  board[d] = ' ';
}

void printBoard() {
 int d;

 char far *target = Screen_base+d;
 for(d=0;d<resolution;d++) {
  *target = board[d];
  *(target+1) = LIGHTGRAY;
  ++target;
  ++target;
 }
}

void ballLogic() {
 vertex newPos = vertexFrom(ballPos);

 if(direction == LEFT)
  newPos.x--;
 if(direction == RIGHT)
  newPos.x++;

 if(newPos.x == 0)
  direction = RIGHT;
 else if(newPos.x == bX)
  direction = LEFT;
 else
  ballPos = vertexFrom(newPos);
}
#包括
#包括
#包括
#包括
#定义bX 80
#定义为24
#定义halfX bX/2
#按/2定义半色调
#通过以下方式定义分辨率bX*
#定义左1
#定义权利2
void GameLoop();
void render();
空挡板();
作废印刷板();
无效逻辑();
类型定义结构{
int x,y;
}顶点;
顶点顶点顶点(int x,int y){
顶点复位;
retVal.x=x;
retVal.y=y;
返回返回;
}
顶点顶点顶点自(顶点自){
顶点复位;
retVal.x=from.x;
retVal.y=from.y;
返回返回;
}
int方向;
char far*屏幕底部;
字符*板;
顶点ballPos;
void main(){
屏幕底部=(字符远*)0xB8000000;
ballPos=顶点,带有(halfX,halfY);
方向=左;
board=(char*)malloc(分辨率*sizeof(char));
GameLoop();
}
void GameLoop(){
字符输入;
clrsc();
透明板();
做{
if(kbhit())
输入=getch();
render();
ballLogic();
延迟(50);
}while(输入!=“p”);
clrsc();
}
void render(){
透明板();
板[ballPos.y*bX+ballPos.x]='x';
印制板();
}
空挡板(){
int d;
对于(d=0;d首先,在代码中:

void printBoard() {
 int d;

 char far *target = Screen_base+d;  // <-- right there
 for(d=0;d<resolution;d++) {
应能够替换为:

A = B;
包含运算符的宏常量周围应该有parenthisis

#define Foo x/2
应该是:

#define Foo (x/2)
这样,无论使用
Foo
的代码是什么,您都不必担心运算符优先级

在16位x86 PC下,实际上有4个显示区域可以切换。如果您可以在其中的2个区域之间切换动画,则动画应该立即发生。这称为双缓冲。您有一个缓冲区作为当前显示缓冲区,另一个缓冲区作为工作缓冲区。然后对工作缓冲区感到满意(如果您试图以一定的速率更新屏幕,那么现在正是时候)然后你交换它们。我不记得怎么做了,但是细节应该不会太难找到。我建议你可以不使用初始缓冲区,在退出时恢复到初始缓冲区,这样程序就可以让屏幕保持它开始时的状态。另外,你可以使用另一个缓冲区来保存调试输出然后,如果你按住空格键或其他东西,缓冲区就会显示出来

如果你不想走那条路线,而“X”是唯一改变的东西,那么你可以放弃清除屏幕,只清除“X”的最后一个位置

屏幕缓冲区不是一个2字节的数组吗?一个用于显示字符,另一个用于属性?我想是的,所以我将它表示为一个数组:

struct screen_unit {
    char ch;
    unsigned char attr;
}; /* or reverse those if I've got them backwards */
这将减少您基于偏移量犯错误的可能性


我可能也会将它们作为16位值而不是字节读写到缓冲区中,尽管这不会有太大的区别。

我找到了它为什么不能立即渲染的原因,我创建的计时器很好。问题是实际时钟只精确到.054547XXX左右,因此我只能以18fps的速度渲染我解决这个问题的方法是使用一个更精确的时钟…这是一个完全不同的故事

您是否尝试过缩短“重复延迟”并最大化“重复率”在“控制面板”的“键盘设置”中?我不明白为什么键盘设置会成为一种研究途径,它不是键盘设置,按住一个键只是出于某种原因导致平滑渲染的一种方式,我想知道为什么“重复延迟”与您的问题完全相关。这意味着,在您的第一个按键事件和后续的流式按键事件之间存在延迟。我建议您在键盘设置中查看这一点。让我们知道您发现了什么。我的重复延迟设置为最快(共4个)下一个栏而我的重复率是最快的。无论我将重复延迟设置为什么,我都会得到相同的结果,但当我将重复率设置为最慢时,我无法实现平滑渲染。这是意料之中的,但它并没有告诉我是什么内在原因导致键盘中断影响我的渲染调用(至少据我所知)顺便说一句,谢谢你的帮助,到目前为止,我觉得我可能正在取得进展。非常好的答案,+1。我同意是kbhit()的C编译器特定实现导致了问题。我用我的C
struct screen_unit {
    char ch;
    unsigned char attr;
}; /* or reverse those if I've got them backwards */