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

时间:2014-05-06 04:32:49

标签: flash opengl 2d

所以我正在制作一个简单的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();

        }
    }



}

3 个答案:

答案 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