尝试制作一个简单的2d游戏,对象闪烁与glutIdleFunc和glutSpecialFunc



我正在创造一款简单的2d游戏,我有一条鱼,它只能吃小鱼。这不是游戏本身的问题,但基本上发生的是我想要其他鱼自己移动,所以我使用了glutIdleFunc,它工作得很好。然而,我想我不是很确定我应该如何使它工作,因为我不希望发生,直到第一个键被按下。我决定把它放在我的handleKey函数中(用于让玩家移动),但现在如果其他鱼移动,我的鱼就会消失,或者当你按住一个键时,你可以看到它在闪烁。我确信这只是在某些时候交换或清除缓冲区的问题,我明白你应该每帧做一次,但我觉得它需要做很多次,我似乎找不到导致我的问题的原因,一双额外的眼睛总是有帮助……我很抱歉这是如此冗长和杂乱无章,我想让它所有的工作之前清理它。

#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h> //used for random numbers
#include <GL/glut.h>
#include <GLGL.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();
        }
    }

}

你有没有试过从任何地方评论glClear(GL_COLOR_BUFFER_BIT);,并在只有一个地方,即在glutDisplayFunc中,在这种情况下,void firstDisplay()

OpenGL的基本规则是:所有绘制只发生在显示例程内,而不是从其他任何地方。没有OpenGL命令必须从输入事件处理程序调用。输入事件处理程序设置/累积到程序变量中,并发布重绘条件。然后让下一个显示迭代绘制更改。

我修复了我的问题,我得到了游戏的工作,感谢大家的输入!!我是新的网站,所以我不知道如何关闭的问题,虽然!

只是作为一个例子,我把我原来的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

最新更新