C++ 游戏挂起,同时更新砖断路器水平。-开放式总账。
我已经用OpenGL和OpenGLUT编写了一个简单的破砖游戏。每件事都按照它应该的方式进行,除了当一个关卡结束时,游戏就挂起了。知道为什么吗? 我试图告诉它重置所有参数,但没有任何效果C++ 游戏挂起,同时更新砖断路器水平。-开放式总账。,c++,opengl,graphics,C++,Opengl,Graphics,我已经用OpenGL和OpenGLUT编写了一个简单的破砖游戏。每件事都按照它应该的方式进行,除了当一个关卡结束时,游戏就挂起了。知道为什么吗? 我试图告诉它重置所有参数,但没有任何效果 #include <GL/openglut.h> #include <cmath> #include <string> #include <ctime> #define RADIUS 0.025 #define P_LENGTH 0.3 using nam
#include <GL/openglut.h>
#include <cmath>
#include <string>
#include <ctime>
#define RADIUS 0.025
#define P_LENGTH 0.3
using namespace std;
int WIDTH = 900,
HEIGHT = 650,
lives = 3,
SCORE = 0,
LEVEL = 2,
BRICK_ROW = 10,
BRICK_COL = 9;
double x_brick[10][10],
y_brick[10][10],
P_XPOS = 0,
P_YPOS = -0.8,
x_pos = 0,
y_pos = -0.75,
win_aspect,
SPEED = 0;
bool show[10][10],
phit_center = false,
phit_corner = false,
game_over = false,
RIGHT = true,
LEFT = false,
UP = true,
DOWN = false,
started = false,
hit = false;
char life = '0';
void user_input(unsigned char key, int x, int y)
{
if(key == 13)
started = true;
}
void b_draw()
{
glBegin(GL_QUADS);
for(int a = 0; a < BRICK_COL; a++)
{
for(int b = 0; b < BRICK_ROW; b++)
{
switch(b)
{
case 0:
glColor3f(1.0,0.0,0.0);
break;
case 1:
glColor3f(1.0,0.9,0.1);
break;
case 2:
glColor3f(0.0,1.0,0.0);
break;
case 3:
glColor3f(0.11,0.56,1.0);
break;
default:
glColor3f(1.0,0.0,0.0);
}
if(show[b][a] == true)
{
glVertex2f(x_brick[b][a]*win_aspect,y_brick[b][a]);
glVertex2f(x_brick[b][a]*win_aspect,(y_brick[b][a] - 0.10));
glVertex2f((x_brick[b][a]+0.2)*win_aspect,(y_brick[b][a] - 0.10));
glVertex2f((x_brick[b][a]+0.2)*win_aspect,y_brick[b][a]);
}
}
}
glColor3f(0.0,0.0,0.0);
glEnd();
}
void Set_Level(int level)
{
int R_Limit = 0;
switch(level)
{
case 1:
for(int a = 0; a < BRICK_ROW; a++)
{
for(int b = 0; b < BRICK_COL; b++)
{
show[a][b] = 1;
}
}
break;
case 2:
for(int a = 0; a < BRICK_ROW/2; a++)
{
for(int b = 0; b < BRICK_COL; b++)
{
if(b >= BRICK_COL/2 - R_Limit && b<=BRICK_COL/2 + R_Limit)
show[a][b] = true;
}
R_Limit++;
}
R_Limit = BRICK_ROW/2;
for(int a = BRICK_ROW/2; a <= BRICK_ROW; a++)
{
for(int b = 0; b <= BRICK_COL; b++)
{
if(b >= BRICK_COL/2 - R_Limit && b <= BRICK_COL/2 + R_Limit)
show[a][b] = true;
}
R_Limit--;
}
break;
case 3:
for(int a = 0; a <= BRICK_COL/2; a++)
{
show[a][a] = true;
}
for(int a = BRICK_COL; a >= BRICK_COL/2; a--)
{
show[BRICK_COL - a - 1][a] = true;
}
break;
}
}
bool all_gone()
{
int local_flag = 0;
for(int a = 0; a < BRICK_COL; a++)
{
for(int b = 0; b < BRICK_ROW; b++)
{
if(show[b][a] == true)
{
return false;
local_flag = 1;
break;
}
if(local_flag)
break;
}
}
return true;
}
void c_draw()
{
glColor3f(0.0f, 0.0f, 0.0f);
glBegin(GL_TRIANGLE_FAN);
glVertex2f(x_pos,y_pos);
for (float angle = 0; angle < (10); angle+=0.01)
{
glVertex2f((x_pos + sin(angle) * RADIUS), (y_pos + (cos(angle)) * RADIUS));
}
glEnd();
}
bool crashed()
{
if(y_pos < P_YPOS - 0.1)
return true;
else return false;
}
void c_move()
{
if(UP && RIGHT)
{
x_pos += SPEED;
y_pos += SPEED;
}
if(UP && LEFT)
{
x_pos -= SPEED;
y_pos += SPEED;
}
if(DOWN && RIGHT)
{
x_pos += SPEED;
y_pos -= SPEED;
}
if(DOWN && LEFT)
{
x_pos -= SPEED;
y_pos -= SPEED;
}
}
void p_draw()
{
glColor3f(0.0,0.0,0.0);
glBegin(GL_QUADS);
glVertex2f(P_XPOS-P_LENGTH, P_YPOS);
glVertex2f(P_XPOS+P_LENGTH, P_YPOS);
glVertex2f(P_XPOS+P_LENGTH, P_YPOS-0.05);
glVertex2f(P_XPOS-P_LENGTH, P_YPOS-0.05);
glEnd();
}
void SET_BRICKS(int level)
{
switch(level)
{
case 1:
BRICK_ROW = 4;
break;
case 2:
BRICK_ROW = 7;
break;
case 3:
BRICK_ROW = 7;
break;
}
}
void BallLoop()
{
const int win_width = glutGet(GLUT_WINDOW_WIDTH),
win_height = glutGet(GLUT_WINDOW_HEIGHT);
win_aspect = (float)win_width/(float)win_height;
glClearColor(1.0, 1.0, 1.0, 0);
glDisable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, win_width, win_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-win_aspect, win_aspect, -1, 1, -1, 1);
c_draw();
b_draw();
p_draw();
life = '0' + lives;
if(started && lives > 0)
c_move();
glFlush();
glutSwapBuffers();
glutPostRedisplay();
}
void GameLogic()
{
if(all_gone())
{
x_pos = 0;
y_pos = -0.7;
LEVEL++;
for(int a = 0; a < BRICK_ROW; a++)
{
for(int b = 0; b <BRICK_COL; b++)
{
show[a][b] = true;
}
}
phit_center = false,
phit_corner = false,
game_over = false,
RIGHT = true,
LEFT = false,
UP = true,
DOWN = false,
started = false,
hit = false;
SET_BRICKS(LEVEL);
Set_Level(LEVEL);
}
if(x_pos >= win_aspect)
{
RIGHT = 0;
LEFT = 1;
}
else if(x_pos <= -win_aspect)
{
RIGHT = 1;
LEFT = 0;
}
if(y_pos >= 1-RADIUS || hit )
{
UP = 0;
DOWN = 1;
}
else if(y_pos <= -1+RADIUS || hit )
{
UP = 1;
DOWN = 0;
}
hit = false;
int flag = 1;
for(int a = 0; a < BRICK_COL; a++)
{
for(int b =0; b < BRICK_ROW; b++)
{
if(x_pos >= x_brick[b][a]*win_aspect && x_pos <= (x_brick[b][a] + 0.2)*win_aspect)
{
if(y_pos <= y_brick[b][a] && y_pos >= y_brick[b][a] - 0.1)
{
if(show[b][a] == 1)
{
show[b][a] = 0;
flag = 0;
hit = true;
break;
}
}
}
}
if(flag == 0)
break;
}
phit_corner = false;
phit_center = false;
if(x_pos <= (P_XPOS + P_LENGTH - 0.05)&& x_pos >= (P_XPOS - P_LENGTH - 0.05))
{
if(y_pos <= P_YPOS)
{
phit_center = true;
}
}
else if((x_pos >=(P_XPOS + P_LENGTH - 0.05) && x_pos <= (P_XPOS + P_LENGTH)) || (x_pos <= (P_XPOS - P_LENGTH + 0.05) && x_pos >= P_XPOS - P_LENGTH))
{
if(y_pos <= P_YPOS)
{
phit_corner = true;
}
}
if(phit_center)
{
DOWN = false;
UP = true;
}
if(phit_corner)
{
if(LEFT)
{
LEFT = false;
RIGHT = true;
}
else
{
RIGHT = false;
LEFT = true;
}
UP = false;
DOWN = true;
}
if(crashed())
{
x_pos = 0;
y_pos = -0.7;
started = false;
UP = true;
RIGHT = true;
DOWN = false;
LEFT = false;
}
BallLoop();
}
void ArrowKeys(int key, int x, int y)
{
if(key==GLUT_KEY_LEFT && P_XPOS >= -0.9*win_aspect)
{
for(float a = 0; a < 0.05; a+= 0.001)
{
P_XPOS -=0.002;
GameLogic();
}
if(!started)
started = true;
}
if(key==GLUT_KEY_RIGHT && P_XPOS <= 0.9*win_aspect)
{
for(float a = 0; a < 0.05; a+= 0.001)
{
P_XPOS +=0.002;
GameLogic();
}
if(!started)
started = true;
}
}
void Init_Game()
{
int c = 0;
for(float a = -0.94; c < BRICK_COL; a+=0.21)
{
for(int b = 0; b <= BRICK_ROW; b++)
{
x_brick[b][c] = a;
}
c++;
}
c = 0;
for(float a = 0.99; c < BRICK_ROW; a-=0.11)
{
for(int b = 0; b < BRICK_COL; b++)
{
y_brick[c][b] = a;
}
c++;
}
}
void set_speed()
{
clock_t start = clock();
for(int a = 1; a < 99999999LLU; a+= 1)
{
;
}
clock_t end = clock();
SPEED = (double)(end - start)/CLOCKS_PER_SEC;
SPEED /= 800;
}
int main(int argc, char **argv)
{
set_speed();
Init_Game();
SET_BRICKS(LEVEL);
Set_Level(LEVEL);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(0,0);
glutInitWindowSize(WIDTH,HEIGHT);
glutCreateWindow("Brick Breaker - By Viraj");
glutKeyboardFunc(user_input);
glutSpecialFunc(ArrowKeys);
glutIdleFunc(GameLogic);
glutDisplayFunc(BallLoop);
glutMainLoop();
return 0;
}
请看一看我作为原始问题答案发布的代码的更正版本 为了简单起见,再次在此处重新发布GLFW版本:
#include <GL/glfw.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
using namespace std;
#define RADIUS 0.025
#define RATIO (4./3.)
bool show[5][10];
float x_brick[4][9];
float y_brick[4][9];
const float SpeedFactor = 1.;
float paddle_x = 0;
float paddle_y = -0.8;
float paddle_speed = 0;
const float PaddleSpeedFactor = 3.;
bool phit_center = false, phit_corner = false;
bool game_over = false;
float speed_x = 0.;
float speed_y = 0.;
float x_pos;
float y_pos;
int lifes = 0;
void draw_bricks()
{
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_QUADS);
for (int a = 0; a < 9; a++) {
for (int b = 0; b < 4; b++) {
if (show[b][a] == 1) {
glVertex2f(x_brick[b][a], y_brick[b][a]);
glVertex2f(x_brick[b][a], y_brick[b][a] - 0.10);
glVertex2f(x_brick[b][a] + 0.2,
y_brick[b][a] - 0.10);
glVertex2f(x_brick[b][a] + 0.2, y_brick[b][a]);
}
}
}
glEnd();
}
void ball_draw()
{
glColor3f(0.0, 0.0, 0.0);
glBegin(GL_TRIANGLE_FAN);
glVertex2f(x_pos, y_pos);
for (float angle = 0; angle < (10); angle += 0.01) {
glVertex2f((x_pos + sin(angle) * RADIUS),
(y_pos + (cos(angle)) * RADIUS));
}
glEnd();
}
bool brick_hit()
{
for (int a = 0; a < 10; a++) {
for (int b = 0; b < 4; b++) {
if (x_pos >= x_brick[b][a]
&& x_pos <= x_brick[b][a] + 0.2) {
if (y_pos <= y_brick[b][a]
&& y_pos >= y_brick[b][a] - 0.1) {
if (show[b][a] == 1) {
show[b][a] = 0;
return true;
}
}
}
}
}
return false;
}
bool crashed()
{
if (y_pos < paddle_y - 0.05)
return true;
return false;
}
void paddle_hit()
{
phit_corner = false;
phit_center = false;
if (x_pos <= paddle_x + 0.13 && x_pos >= paddle_x - 0.13) {
if (y_pos <= paddle_y) {
phit_center = true;
}
} else if ((x_pos >= paddle_x + 0.13 && x_pos <= paddle_x + 0.2) ||
(x_pos <= paddle_x - 0.13 && x_pos >= paddle_x - 0.2)) {
if (y_pos <= paddle_y) {
phit_corner = true;
}
}
}
void paddle_move(float dT)
{
if (paddle_x < RATIO && paddle_x > -RATIO)
paddle_x += paddle_speed * PaddleSpeedFactor * dT;
if (paddle_x > 1.) {
paddle_x = 1.;
paddle_speed = 0.;
}
if (paddle_x < -1.) {
paddle_x = -1.;
paddle_speed = 0.;
}
}
void ball_move(float dT)
{
x_pos += speed_x * dT;
y_pos += speed_y * dT;
if (brick_hit()) {
speed_y *= -1;
}
if (x_pos >= (RATIO - RADIUS) || x_pos <= (-RATIO + RADIUS)) {
speed_x *= -1;
}
if (y_pos >= (1. - RADIUS)) {
speed_y *= -1;
}
paddle_hit();
if (phit_center) {
speed_y *= -1;
speed_x += 0.5 * paddle_speed;
}
if (phit_corner) {
speed_x = -speed_x + 0.2 * paddle_speed;
speed_y *= -1;
}
if( (speed_x * speed_x + speed_y * speed_y) > 0.001 ) {
float k = 1./sqrt(speed_x * speed_x + speed_y * speed_y);
speed_x *= k;
speed_y *= k;
}
}
void paddle_draw()
{
glColor3f(0.0, 0.0, 0.0);
glBegin(GL_QUADS);
glVertex2f(paddle_x - 0.2, paddle_y);
glVertex2f(paddle_x + 0.2, paddle_y);
glVertex2f(paddle_x + 0.2, paddle_y - 0.05);
glVertex2f(paddle_x - 0.2, paddle_y - 0.05);
glEnd();
}
void set_xy();
void reset_game()
{
set_xy();
lifes = 3;
speed_x = 0;
speed_y = 0;
x_pos = 0;
y_pos = -0.7;
paddle_speed = 0;
paddle_x = 0;
}
void step_game(float dT)
{
if(!lifes)
return;
paddle_move(dT * SpeedFactor);
ball_move(dT * SpeedFactor);
if (crashed()) {
lifes--;
speed_x = 0;
speed_y = 0;
x_pos = 0;
y_pos = -0.7;
}
}
static float frandom(float a, float b)
{
return a + (b - a) * (float)random() / (float)RAND_MAX;
}
void launch_ball()
{
if(!lifes)
return;
speed_y = 1.;
speed_x = frandom(-1., 1.);
float k = 1./sqrt(speed_x * speed_x + speed_y + speed_y);
speed_x *= k;
speed_y *= k;
}
void keyboard(int key, int action)
{
switch(key)
{
case GLFW_KEY_ENTER:
launch_ball();
break;
case GLFW_KEY_ESC:
reset_game();
break;
case GLFW_KEY_LEFT:
switch(action) {
case GLFW_PRESS:
paddle_speed = -1.;
break;
case GLFW_RELEASE:
paddle_speed = 0;
break;
} break;
case GLFW_KEY_RIGHT:
switch(action) {
case GLFW_PRESS:
paddle_speed = 1.;
break;
case GLFW_RELEASE:
paddle_speed = 0;
break;
} break;
}
}
void set_xy()
{
for (int a = 0; a < 5; a++) {
for (int b = 0; b < 10; b++) {
show[a][b] = 1;
}
}
int c = 0;
for (float a = -0.94; c <= 8; a += 0.21, c++) {
for (int b = 0; b <= 5; b++) {
x_brick[b][c] = a;
}
}
int d = 0;
for (float s = 0.99; d <= 3; s -= 0.11, d++) {
for (int r = 0; r < 9; r++) {
y_brick[d][r] = s;
}
}
}
float display()
{
int win_width;
int win_height;
glfwGetWindowSize(&win_width, &win_height);
const float win_aspect = (float)win_width / (float)win_height;
glfwSetTime(0.);
glViewport(0, 0, win_width, win_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (win_aspect > RATIO) {
glOrtho(-win_aspect, win_aspect, -1., 1., -1., 1.);
} else {
glOrtho(-RATIO, RATIO, -RATIO / win_aspect, RATIO / win_aspect,
-1., 1.);
}
glMatrixMode(GL_MODELVIEW);
glClearColor(0., 0., 1., 1.);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_QUADS);
glColor3f(1, 1, 1);
glVertex2f(-RATIO, -1);
glVertex2f(RATIO, -1);
glVertex2f(RATIO, 1);
glVertex2f(-RATIO, 1);
glEnd();
draw_bricks();
paddle_draw();
ball_draw();
glfwSwapBuffers();
return glfwGetTime();
}
int main(int argc, char **argv)
{
srandom(time(0));
set_xy();
if( GL_FALSE == glfwInit() )
return -1;
if( GL_FALSE == glfwOpenWindow(800, 600, 8, 8, 8, 8, 0, 0, GLFW_WINDOW) )
return -2;
glfwSetWindowTitle("Viraj's Brick Breaker - GLFW version by datenwolf");
glfwSetKeyCallback(keyboard);
reset_game();
while( glfwGetWindowParam(GLFW_OPENED) ) {
glfwPollEvents();
float const dT = display();
step_game(dT);
}
glfwTerminate();
return 0;
}
该内部for循环将使桨叶对关键点做出反应,并在该动画发生时,所有进一步的用户输入将堆积起来,导致奇怪的运动。永远不要这样做。在输入处理程序中,设置一些状态变量,这些变量会影响空闲循环中的游戏逻辑。但永远不要直接从输入处理程序设置动画
请看一下我的代码,编译它,执行它。并尝试理解游戏逻辑、渲染和输入处理之间的分离。我听说不建议使用。好吧,这是你的问题。如果你使用的工具坏了,无法进行调试,请使用一个没有坏的工具。不要使用Dev-C++,这是一堆废话,不是IDE。@viraj:除了Dev-C++,什么都可以。我发布的链接为您提供了很多其他选择,老实说,如果您可以选择一个因其配色方案而不喜欢的编辑器,还是一个没有调试器的编辑器,请选择第一个。说我选择使用一个坏的工具是因为我最喜欢它的配色方案,这意味着我甚至没有试着调试我的代码,这反过来意味着这里的人不太可能想帮助你。如果您需要帮助设置Eclipse,请在下面询问。不要只是说我会继续使用不起作用的IDEinstead@viraj:除了Dev废话以外的任何东西。C::B和Eclipse都是不错的选择。Visual Studio也是。或者是任何像样的文本编辑器,真的。你怎么猜到的?我还在学校,所以我先学习QBASIC,然后再看VisualBasic,然后再转到C++。关于编码风格,我想你是指我存储行空间和使用{}的方式吧?此外,您在聊天时也停止了回复。我尝试在DeV C++上使用GLFW,并在DeVCPP上安装DEV包,但每次编译代码时,它都会成功编译,但不会出现窗口。大约两分钟后,防病毒程序将其标记为病毒。回到程序,我试图做与你的重置游戏功能相同的事情,但是在内部。它似乎不起作用。我所说的编码风格是指如何使用变量、函数等。您的代码的结构类似于基本程序。许多C代码编写者会认为这是一种侮辱;直到现在,我才对聊天做出反应,因为我是离线的。@viraj:最能说明问题的迹象是,sonebody在思想上陷入了一个基本世界,那就是使用全局变量。虽然将全局状态放在全局变量中没有错,但函数之间传递的数据应该通过参数传递。
void ArrowKeys(int key, int x, int y)
{
if(key==GLUT_KEY_LEFT && P_XPOS >= -0.9*win_aspect)
{
for(float a = 0; a < 0.05; a+= 0.001)
{
P_XPOS -=0.002;
GameLogic();
}