所以我正在制作一个简单的2D游戏,我有一条只需要吃小鱼的鱼。游戏本身并没有真正的问题,但基本上发生的事情是我希望其他鱼自己移动,所以我使用glutIdleFunc来做到这一点。但是,我想我不确定我应该如何使它工作,因为我不希望在第一个按键被按下之前发生这种情况。我决定将它放在我的handleKey函数中(用于让玩家移动)但是现在我的鱼会在其他鱼移动时消失,或者当你按住一个键时你可以看到它闪烁。我确定在某些时候交换或清除缓冲区只是一个问题,我知道你应该每帧做一次,但我觉得它需要像我一样多次完成,我可以'似乎找到了导致我的问题的原因,额外的一双眼睛总是有帮助...我很抱歉它是如此冗长和无组织,我想在清理它之前完成所有工作。
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h> //used for random numbers
#include <GL/glut.h>
#include <GL\GL.h>
#include <math.h>
#include <iostream>
using namespace std;
#define X WIDTH/2
#define Y HEIGHT/2
#define PI 3.14159
#define INC .001
const int WIDTH = 720;
const int HEIGHT = 480;
const int numFish=10;
const int playerEyeRad=2;
const int eyeRad=1;
const int sharkEyeRad=3;
static float mouthSize = .7;
static int mouthOpen=0;
static int score=1;
static int lives=3;
bool gameRunning = true;
void *font = GLUT_BITMAP_TIMES_ROMAN_24;
struct Player
{
int x,y;
GLfloat deltax;
GLfloat deltay;
GLfloat spin;
GLfloat scaleX;
GLfloat scaleY;
GLfloat scaleZ;
};
Player playerFish;
struct Fish
{
int x,y;
int size;
GLfloat deltax;
GLfloat deltay;
GLfloat spin;
GLfloat scale;
bool goingLeft;
bool goingRight;
bool goingUp;
bool goingDown;
};
Fish cpFish[numFish];
Fish barracuda;
char defaultMessage[] = "Fish game";
char *message = defaultMessage;
void initialize();
void output(int x, int y, char *string);
void firstDisplay();
void drawPlayer(int x, int y);
void translatePlayer(int key);
void handleKey(int key,int x,int y); //function to handle when we press a key
void drawFish(int x, int y,int eyerad);
void setFish();
void displayFish();
void translateFish();
void eat(int numFish);
void endGame();
void setBarracuda();
void drawBarracuda(int x, int y);
void translateBarracuda();
void barracudaEat();
void setPlayer();
int _tmain(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_MULTISAMPLE);
glutInitWindowSize(WIDTH,HEIGHT);
glutCreateWindow("Fish Game");
initialize();
setPlayer();
setFish();
setBarracuda();
glutDisplayFunc(firstDisplay);
glutSpecialFunc(handleKey);
glutMainLoop();
return 0;
}
void initialize()
{
glClearColor(.098,.14,.96,0);
glColor3f(1,1,1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0,WIDTH,0,HEIGHT);
return;
}
void output(int x, int y, char *string)
{
int len, i;
glRasterPos2f(x,y);
len = (int) strlen(string);
for(i=0;i<len;i++){
glutBitmapCharacter(font,string[i]);
}
return;
}
void firstDisplay()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0,0,0);
output(X,Y, message);
output (X, Y - 40,"by");
output(X,Y - 80,"derp");
drawBarracuda(barracuda.x,barracuda.y);
displayFish();
drawPlayer(playerFish.x,playerFish.y);
glutSwapBuffers();
glFlush();
return;
}
void setPlayer()
{
playerFish.x=100;
playerFish.y=200;
playerFish.scaleX=1;
playerFish.scaleY=1;
playerFish.scaleZ=1;
playerFish.spin=0;
playerFish.deltax=0;
playerFish.deltay=0;
}
void drawPlayer(int x, int y)
{
float theta;
//glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POLYGON); // fish body
glColor3f(.56,.035,.035);
for(theta=0;theta<2*PI;theta+=INC)
{
glVertex2f(x + 20* cos(theta),y + 10 * sin(theta));
}
glEnd();
glBegin(GL_TRIANGLES); //bottom of fish tail
glColor3f(.56,.035,.035);
glVertex2i((x-35),(y-10));
glVertex2i((x-5),(y-5));
glVertex2i((x-20),y);
glEnd();
glBegin(GL_TRIANGLES); //top of fish tail
glColor3f(.56,.035,.035);
glVertex2i((x-35),(y+10));
glVertex2i((x-5),y);
glVertex2i((x-20),(y-5));
glEnd();
glBegin(GL_POLYGON); //fish eye
glColor3f(0,0,0);
for(theta=0;theta<2*PI;theta+=INC)
{
glVertex2f((x+7) + playerEyeRad * cos(theta),(y+3) + playerEyeRad * sin(theta));
}
glEnd();
glBegin(GL_POLYGON); //fish mouth
glColor3f(.098,.14,.96);
//glColor3f(0,0,0);
glVertex2i(112,198);
for(theta=-mouthSize;theta<mouthSize;theta+=INC)
{
glVertex2f(x + 20 * cos(theta),y + 10 * sin(theta));
}
glEnd();
glEnable(GL_LINE_STIPPLE); //stipple the gills
short stipplePattern=0x3F07;
glColor3f(0,0,0);
glBegin(GL_LINES);
glLineStipple(1,stipplePattern);
glVertex2i(x,(y-2));
glVertex2i((x+5),(y-2));
glEnd();
glBegin(GL_LINES);
glLineStipple(1,stipplePattern);
glVertex2i(x,(y-5));
glVertex2i((x+5),(y-5));
glEnd();
glDisable(GL_LINE_STIPPLE); //disable stipple, end of gills
return;
}
void translatePlayer(int key)
{
glClear(GL_COLOR_BUFFER_BIT);
if (key==GLUT_KEY_RIGHT && (playerFish.x + playerFish.deltax) < WIDTH - 20)
{
playerFish.deltax+=6;
playerFish.spin=0;
}
if (key==GLUT_KEY_LEFT && (playerFish.x + playerFish.deltax) > 20)
{
playerFish.deltax-=6;
playerFish.spin=180;
}
if (key==GLUT_KEY_UP && (playerFish.y + playerFish.deltay) < HEIGHT - 20)
{
playerFish.deltay+=6;
playerFish.spin=90;
}
if (key==GLUT_KEY_DOWN && (playerFish.y + playerFish.deltay) > 20)
{
playerFish.deltay-=6;
playerFish.spin=270;
}
if (score%5==0)
{
playerFish.scaleX++;
playerFish.scaleY++;
playerFish.scaleZ++;
score=1;
playerFish.x=(playerFish.x + playerFish.deltax )* playerFish.scaleX;
playerFish.y=(playerFish.y + playerFish.deltay) * playerFish.scaleY;
}
glPushMatrix(); //push on translation matrix
glTranslatef(playerFish.x + playerFish.deltax, playerFish.y + playerFish.deltay,0.0); //translate back to position
glScalef(playerFish.scaleX,playerFish.scaleY,playerFish.scaleZ);
if (key==GLUT_KEY_LEFT) // stops player from going upside down
glRotatef(playerFish.spin,0,-1,0); //reflect y axis
else
glRotatef(playerFish.spin,0,0,1); // spin
glTranslatef(-playerFish.x,-playerFish.y,0.0); //translate back to origin
drawPlayer(playerFish.x, playerFish.y); //draw player to screen
glPopMatrix(); // pop the matrix
glutSwapBuffers(); //swap the buffers
//glFlush();
if (!gameRunning || playerFish.scaleX>=6|| lives <=0)
endGame();
// mouth open close
if(mouthSize < .05 && mouthOpen==0)
{
mouthSize = .7;
mouthOpen++;
}
else
{
mouthSize=.007;
mouthOpen++;
if (mouthOpen==5)
mouthOpen=0;
}
return;
}
//function used to handle keys being pressed
//param int key ascii value of key being pressed, int x, int y coordinates the glutspecialfunc requires
//return void
void handleKey(int key,int x,int y)
{
//glClear(GL_COLOR_BUFFER_BIT);//clear the buffer bit
//drawPlayer(playerFish.x + playerFish.deltax,playerFish.y+playerFish.deltay);
//glutIdleFunc(translateFish);
glutIdleFunc(NULL);
if(key == GLUT_KEY_DOWN ||key == GLUT_KEY_UP ||key == GLUT_KEY_LEFT ||key == GLUT_KEY_RIGHT) // if any of the arrow keys are being pressed
{
if (gameRunning && playerFish.scaleX <6 && lives > 0)
{
translatePlayer(key); //call on the translate function using the key integer value
glFlush();
//glutSwapBuffers();
//glutIdleFunc(translateFish);
}
}
glutIdleFunc(translateFish);
glFlush();
//glutSwapBuffers();
return;
}//end handleKey
void drawFish(int x, int y, int eyeRad)
{
float theta;
glBegin(GL_POLYGON); // fish body
glColor3f(.8,.75,.023);
for(theta=0;theta<2*PI;theta+=INC)
{
glVertex2f(x + 10* cos(theta),y + 5 * sin(theta));
}
glEnd();
glBegin(GL_TRIANGLES); //bottom of fish tail
glColor3f(.8,.75,.023);
glVertex2i((x-15),(y-5));
glVertex2i((x-10),y);
glVertex2i(x,(y-5));
glEnd();
glBegin(GL_TRIANGLES); //top of fish tail
glColor3f(.8,.75,.023);
glVertex2i((x-15),(y+5));
glVertex2i(x,y);
glVertex2i((x-10),(y-5));
glEnd();
glBegin(GL_POLYGON); //fish eye
glColor3f(0,0,0);
for(theta=0;theta<2*PI;theta+=INC)
{
glVertex2f((x+5) + eyeRad * cos(theta),(y+3) + eyeRad * sin(theta));
}
glEnd();
return;
}
//function used to set x and y values for the computer fish
//param none
//return void
void setFish()
{
int counter;
int randX;
int randY;
for(counter=0;counter<numFish;counter++)
{
randX = (1+rand() % (WIDTH-50));
randY = (1+ rand() % (HEIGHT-50));
cpFish[counter].x=randX;
cpFish[counter].y=randY;
cpFish[counter].size=1;
cpFish[counter].goingUp=true;
cpFish[counter].goingDown=false;
cpFish[counter].goingRight=true;
cpFish[counter].goingLeft=false;
}
return;
}
//function used to display the fish to the screen
void displayFish()
{
int counter;
for(counter=0;counter<numFish;counter++)
{
//cout<<"Drawing fish to screen at position: "<<cpFish[counter].x<<" \t" <<cpFish[counter].y<<endl;
drawFish(cpFish[counter].x,cpFish[counter].y,eyeRad);
}
return;
}
void translateFish()
{
int fishNum;
glClear(GL_COLOR_BUFFER_BIT);
for(fishNum=0;fishNum<numFish;fishNum++)
{
if ((cpFish[fishNum].deltax + cpFish[fishNum].x)< WIDTH - 20 && cpFish[fishNum].goingRight)
{
cpFish[fishNum].deltax +=3;
cpFish[fishNum].spin=0;
if ((cpFish[fishNum].deltax + cpFish[fishNum].x) >= WIDTH - 20)
{
cpFish[fishNum].goingRight=false;
cpFish[fishNum].goingLeft=true;
}
} // end right if
if ((cpFish[fishNum].deltax + cpFish[fishNum].x)> 20 && cpFish[fishNum].goingLeft)
{
cpFish[fishNum].deltax -=3;
cpFish[fishNum].spin = 180;
if ((cpFish[fishNum].deltax + cpFish[fishNum].x)<= 20)
{
cpFish[fishNum].goingLeft=false;
cpFish[fishNum].goingRight=true;
}
}// end left if
if ((cpFish[fishNum].deltay + cpFish[fishNum].y)< HEIGHT - 20 && cpFish[fishNum].goingUp)
{
cpFish[fishNum].deltay +=3;
if ((cpFish[fishNum].deltay + cpFish[fishNum].y)>= HEIGHT - 20)
{
cpFish[fishNum].goingUp=false;
cpFish[fishNum].goingDown=true;
}
} // end up if
if ((cpFish[fishNum].deltay + cpFish[fishNum].y)> 20 && cpFish[fishNum].goingDown)
{
cpFish[fishNum].deltay -=3;
if ((cpFish[fishNum].deltay + cpFish[fishNum].y) <= 20)
{
cpFish[fishNum].goingDown=false;
cpFish[fishNum].goingUp=true;
}
}// end down if
glPushMatrix();
glTranslatef(cpFish[fishNum].x + cpFish[fishNum].deltax,cpFish[fishNum].y + cpFish[fishNum].deltay,0);
if(cpFish[fishNum].goingLeft)
glRotatef(cpFish[fishNum].spin,0,-1,0);
else
glRotatef(cpFish[fishNum].spin,0,0,1);
glTranslatef(-cpFish[fishNum].x,-cpFish[fishNum].y,0);
drawFish(cpFish[fishNum].x,cpFish[fishNum].y,eyeRad);
glPopMatrix();
eat(fishNum);
// cout<<"Fish "<<fishNum<<"'s deltax + x: "<<cpFish[fishNum].deltax + cpFish[fishNum].x <<" \t deltay: "<<cpFish[fishNum].deltay + cpFish[fishNum].y<<endl;
//cout<<"Going up = "<<cpFish[fishNum].goingUp<<"going down "<<cpFish[fishNum].goingDown<<" going Right "<<cpFish[fishNum].goingRight<<" going left "<<cpFish[fishNum].goingLeft<<endl;
}
translateBarracuda();
glutSwapBuffers();
return;
}
void eat(int numFish)
{
int playerSize=playerFish.scaleX;
int fishSize=cpFish[numFish].size;
int playerX=playerFish.x + playerFish.deltax;
int playerY = playerFish.y + playerFish.deltay;
int cpX=cpFish[numFish].x+cpFish[numFish].deltax;
int cpY=cpFish[numFish].y+cpFish[numFish].deltay;
int newX = (1+rand() % (WIDTH-50));
int newY= (1+ rand() % (HEIGHT-50));
//cout<<"PLAYER'S X: "<<playerX<<"\t PLAYER'S Y: "<<playerY<<"\t FISH" <<numFish<<" X "<<cpX<< "\t FISH "<<numFish<<" Y: " <<cpY<<endl;
if ((fishSize <= playerSize)&&((cpX - playerX >= (-10*playerFish.scaleX)) && (cpX - playerX <= (10*playerFish.scaleX)) )&&((cpY - playerY >= (-10*playerFish.scaleY)) &&(cpY - playerY <= (10*playerFish.scaleY))))
{
cpFish[numFish].x = newX;
cpFish[numFish].y = newY;
score++;
cpFish[numFish].goingUp=true;
cpFish[numFish].goingDown=false;
cpFish[numFish].goingRight=true;
cpFish[numFish].goingLeft=false;
cpFish[numFish].deltax=0;
cpFish[numFish].deltay=0;
drawFish(cpFish[numFish].x,cpFish[numFish].y, eyeRad);
}
if (playerSize==6)
gameRunning=false;
}
void endGame()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0,0,0);
glClearColor(1,1,1,0);
if (!gameRunning || playerFish.scaleX>=6)
{
output(X,Y,"You win!");
//exit;
}
else
{
if (lives<=0)
{
output(X,Y,"Game over, you lost");
// exit;
}
}
glutSwapBuffers();
}
void drawBarracuda(int x, int y)
{
float theta;
glBegin(GL_POLYGON); // fish body
glColor3f(.596,.596,.576);
for(theta=0;theta<2*PI;theta+=INC)
{
glVertex2f(x + 45* cos(theta),y + 10 * sin(theta));
}
glEnd();
glBegin(GL_TRIANGLES); //bottom of fish tail
glColor3f(.596,.596,.576);
glVertex2i((x-55),(y-10));
glVertex2i((x-25),(y-5));
glVertex2i((x-40),y);
glEnd();
glBegin(GL_TRIANGLES); //top of fish tail
glColor3f(.596,.596,.576);
glVertex2i((x-55),(y+10));
glVertex2i((x-25),y);
glVertex2i((x-40),(y-5));
glEnd();
glBegin(GL_POLYGON); //fish eye
glColor3f(0,0,0);
for(theta=0;theta<2*PI;theta+=INC)
{
glVertex2f((x+7) + sharkEyeRad * cos(theta),(y+3) + sharkEyeRad * sin(theta));
}
glEnd();
glBegin(GL_POLYGON); //fish mouth
glColor3f(.098,.14,.96);
//glColor3f(0,0,0);
glVertex2i((x+12),(y-2));
for(theta=-mouthSize;theta<mouthSize;theta+=INC)
{
glVertex2f(x + 45 * cos(theta),y + 10 * sin(theta));
}
glEnd();
glEnable(GL_LINE_STIPPLE); //stipple the gills
short stipplePattern=0x3F07;
glColor3f(0,0,0);
glBegin(GL_LINES);
glLineStipple(1,stipplePattern);
glVertex2i((x-10),(y-2));
glVertex2i((x-5),(y-2));
glEnd();
glBegin(GL_LINES);
glLineStipple(1,stipplePattern);
glVertex2i((x-10),(y-5));
glVertex2i((x-5),(y-5));
glEnd();
glDisable(GL_LINE_STIPPLE); //disable stipple, end of gills
}
void setBarracuda()
{
barracuda.x=100;
barracuda.y=350;
barracuda.size=3;
barracuda.goingLeft=false;
barracuda.goingRight=true;
barracuda.goingUp=false;
barracuda.goingDown=false;
}
void translateBarracuda()
{
if ((barracuda.deltax + barracuda.x)< WIDTH - 20 && barracuda.goingRight)
{
barracuda.deltax +=9;
barracuda.spin=0;
if ((barracuda.deltax + barracuda.x) >= WIDTH - 20)
{
int newX=100;
int newY=(1 + rand() % HEIGHT);
drawBarracuda(newX,newY);
barracuda.x=newX;
barracuda.y=newY;
barracuda.deltax=0;
barracuda.deltay=0;
}
} // end right if
glPushMatrix();
glTranslatef(barracuda.x + barracuda.deltax,barracuda.y + barracuda.deltay,0);
glRotatef(barracuda.spin,0,0,1);
glTranslatef(-barracuda.x,-barracuda.y,0);
drawBarracuda(barracuda.x,barracuda.y);
glPopMatrix();
barracudaEat();
}
void barracudaEat()
{
int playerSize=playerFish.scaleX;
int barracudaSize=barracuda.size;
int barracudaPosX = barracuda.x + barracuda.deltax;
int barracudaPosY = barracuda.y + barracuda.deltay;
int playerX = playerFish.x + playerFish.deltax;
int playerY = playerFish.y + playerFish.deltay;
if ((playerSize < barracudaSize)&&((playerX - barracudaPosX >= (-10*playerFish.scaleX)) && (playerX - barracudaPosX <= (10*playerFish.scaleX)) )&&((playerY - barracudaPosY >= (-10*playerFish.scaleY)) &&(playerY - barracudaPosY <= (10*playerFish.scaleY))))
{
lives--;
playerFish.x = 100;
playerFish.y = 200;
playerFish.deltax=0;
playerFish.deltay=0;
playerFish.spin=0;
playerFish.scaleX=1;
playerFish.scaleY=1;
playerFish.scaleZ=1;
if (lives==0)
{
endGame();
}
}
else
{
if ((playerSize >= barracudaSize)&&((playerX - barracudaPosX >= (-10*playerFish.scaleX)) && (playerX - barracudaPosX <= (10*playerFish.scaleX)) )&&((playerY - barracudaPosY >= (-10*playerFish.scaleY)) &&(playerY - barracudaPosY <= (10*playerFish.scaleY))))
{
drawBarracuda(0,600);
barracuda.x=0;
barracuda.y=600;
gameRunning=false;
endGame();
}
}
}
答案 0 :(得分:0)
您是否尝试过从任何地方评论glClear(GL_COLOR_BUFFER_BIT);
,并且只在一个地方(即在glutDisplayFunc中),在这种情况下void firstDisplay()
答案 1 :(得分:0)
OpenGL的基本规则是:所有绘图仅在显示例程中发生,而不是从其他任何地方发生。不能从输入事件处理程序调用OpenGL命令。输入事件处理程序设置/累积到程序变量中并发布重绘条件。然后让下一个显示迭代绘制更改。
答案 2 :(得分:0)
我修复了我的问题,让游戏开始工作,谢谢大家的投入!我是网站的新手,所以我不知道如何关闭这个问题!
就像一个例子,我使用了原始的translatePlayer函数并将其分解为updateFunction。您在此函数中看到的所有内容都是从translatePlayer函数中删除的
void updatePlayer()
{
//opens and closes the player's mouth but not each time the key is pressed
if(mouthSize < .05 && mouthOpen==0)
{
mouthSize = .7;
mouthOpen++;
}
else
{
mouthSize=.007;
mouthOpen++;
if (mouthOpen==5)
mouthOpen=0;
}
//All the transformations for the player happen here
glPushMatrix(); //push on translation matrix
glTranslatef(playerFish.x + playerFish.deltax, playerFish.y + playerFish.deltay,0.0); //translate back to position
glScalef(playerFish.scaleX,playerFish.scaleY,playerFish.scaleZ);
if (playerFish.spin==180) // stops player from going upside down
glRotatef(playerFish.spin,0,-1,0); //reflect y axis
else
glRotatef(playerFish.spin,0,0,1); // spin
glTranslatef(-playerFish.x,-playerFish.y,0.0); //translate back to origin
drawPlayer(playerFish.x, playerFish.y); //draw player to screen
glPopMatrix(); // pop the matrix
//the player gets scaled according to the score variable, then gets reset back to 1 so the player isn't always being scaled up
if (score%5==0)
{
playerFish.scaleX++;
playerFish.scaleY++;
playerFish.scaleZ++;
score=1;
}
} //end updatePlayer