球赛:项目

时间:2015-03-28 16:35:52

标签: c opengl

我正在进行一项项目,其中一个球将随机运动,分数显示在左上角,计时器功能在右上角1分钟。 目的是玩家将点击球并且得分将增加1并且球的速度将增加。 直到现在我已经进行了随机动作,得分显示但是我无法计算球的位置,就像光标越过球时那样,否则需要显示得分。所以帮助我检测移动球上的鼠标。这是我的代码:

    #include<GL/glut.h> 
#include<math.h> 
#include<stdbool.h> 
#include<stdio.h> 
#define PI 3.14159265f 


GLfloat ballRadius = 0.2; 
GLfloat ballX = 0.0f; 
GLfloat ballY = 0.0f; 
GLfloat ballXMax,ballXMin,ballYMax,ballYMin; 
GLfloat xSpeed = 0.02f; 
GLfloat ySpeed = 0.007f; 
int refreshMills = 30; 
int x1,xa,ya; 
int score = 0; 
int last_mx = 0, last_my = 0, cur_mx = 0, cur_my = 0; 
int arcball_on = false; 
int posx = -1,posy=0,posz=1; 
char *string; 
GLdouble clipAreaXLeft,clipAreaXRight,clipAreaYBottom,clipA reaYTop; 




void color() 
{ 
     if(score<=5) 
          glColor3f(1.0,0.0,0.0); 
     else 
          glColor3ub( rand()%250, rand()%250, rand()%250 ); 
}    
void balldisp() 
{ 
    glTranslatef(ballX,ballY,0.0f); 
    glBegin(GL_TRIANGLE_FAN); 
    color(); 
    glVertex2f(0.0f,0.0f); 
    int numSegments = 100; 

    GLfloat angle; 
    int i; 
    for(i=0;i<=numSegments;i++) 
    { 
         angle = i*2.0f*PI/numSegments; 
         glVertex2f(cos(angle)*ballRadius,sin(angle)*ballRa dius); 
    } 
    glEnd(); 

    ballX += xSpeed; 
    ballY += ySpeed; 

   if(ballX > ballXMax) 
   {
        xa=ballX; 
        ballX = ballXMax; 
        xSpeed = -xSpeed; 

   } 
   else if(ballX < ballXMin) 
   { 
        xa=ballX; 
        ballX = ballXMin; 
        xSpeed = -xSpeed; 

    } 
   if(ballY > ballYMax) 
   { 
        ya=ballY; 
        ballY = ballYMax; 
        ySpeed = -ySpeed; 

   } 
   else if(ballY < ballYMin) 
   { 
        ya=ballY; 
        ballY = ballYMin; 
        ySpeed = -ySpeed; 

    } 
} 

void scoredisp() 
{ 
    int z,j=0,k=0; 
    z=score; 
    glColor3f(1.0,0.0,0.0); 
    glLoadIdentity(); 
    glRasterPos2f(-1,1 ); 
    glutBitmapCharacter (GLUT_BITMAP_TIMES_ROMAN_24,'S'); 
    glutBitmapCharacter (GLUT_BITMAP_TIMES_ROMAN_24,'C'); 
    glutBitmapCharacter (GLUT_BITMAP_TIMES_ROMAN_24,'O'); 
    glutBitmapCharacter (GLUT_BITMAP_TIMES_ROMAN_24,'R'); 
    glutBitmapCharacter (GLUT_BITMAP_TIMES_ROMAN_24,'E'); 
    glutBitmapCharacter (GLUT_BITMAP_TIMES_ROMAN_24,' '); 
    glutBitmapCharacter (GLUT_BITMAP_TIMES_ROMAN_24,':'); 

    while(z > 9) 
    { 
        k = z % 10; 
        glRasterPos2f (-0.58,1); 
        glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24,48+ k); 
        z /= 10; 
        glRasterPos2f(-0.62,1); 
     } 
     glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24,48+ z); 
} 

void display() 
{ 
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    balldisp(); 
    scoredisp(); 
    glFlush(); 
} 
void onMouse(int button, int state, int x, int y) /// I want help here to detect mouse over the ball 
{ 



    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) 
    { 
        arcball_on = true; 
        cur_mx = x; 
        cur_my = y; 

    } 
    else 
    { 
        arcball_on = false; 
        if(cur_mx==x && cur_my==y) 
        { 
            score=score+1; 
        } 
        printf("%d",score); 
    } 



//return score; 

// xSpeed=xSpeed+0.02; 
// ySpeed=ySpeed+0.002; 
} 
void onMotion(int x, int y) 
{ 
    if (arcball_on)
    { 
        cur_mx = x; 
        cur_my = y; 
        printf("%d",cur_mx);
    } 
} 


void reshape(GLsizei width,GLsizei height) 
{ 
    if(height ==0) height = 1; 
        GLfloat aspect = (GLfloat)width / (GLfloat)height; 
        glViewport(0,0,width,height); 
        glMatrixMode(GL_PROJECTION); 
        glLoadIdentity(); 
    if(width >=height) 
    { 
        clipAreaXLeft = -1.0 * aspect; 
        clipAreaXRight = 1.0 * aspect; 
        clipAreaYBottom = -1.0; 
        clipAreaYTop = 1.0; 
    } 
    else 
    { 
        clipAreaXLeft = -1.0; 
        clipAreaXRight = 1.0 ; 
        clipAreaYBottom = -1.0 / aspect; 
        clipAreaYTop = 1.0/ aspect; 
    } 
    gluOrtho2D(clipAreaXLeft,clipAreaXRight,clipAreaYB ottom,clipAreaYTop+0.10); 
    ballXMin = clipAreaXLeft + ballRadius; 
    ballXMax = clipAreaXRight - ballRadius; 
    ballYMin = clipAreaYBottom + ballRadius; 
    ballYMax = clipAreaYTop - ballRadius; 
} 

void Timer(int value) 
{ 
    glutPostRedisplay(); 
    glutTimerFunc(refreshMills,Timer,5); 
} 

int main(int argc,char* argv[]) 
{ 
    glutInit(&argc,argv); 
    glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB); 
    glutInitWindowSize(500,500); 
    glutInitWindowPosition(100,100); 
    glutCreateWindow("Bouncing Ball"); 
    glutMouseFunc(onMouse); 
    glutMotionFunc(onMotion); 
    glutDisplayFunc(display); 
    glutReshapeFunc(reshape); 
    glutPostRedisplay(); 
    glutTimerFunc(0,Timer,0); 
    glutMainLoop(); 

}

1 个答案:

答案 0 :(得分:0)

您可以使用距离公式来判断鼠标是否正在接触球。

  1. 将点击位置从窗口坐标转换为世界坐标。
  2. 计算球心和鼠标之间的距离。
  3. 如果距离小于球半径,则鼠标正在触摸。
  4. 将鼠标位置从窗口转换为世界坐标

    由于您拥有固定的摄像机位置和预定义的窗口大小,您可以这样做,但它不是非常通用。

    void windowToWorld(int windowX, int windowY, GLdouble *worldX, GLdouble *worldY){
        int x = windowX - 500 / 2;
        int y = windowY - 500 / 2;
    
        *worldX = (double)x / 250.0;
        *worldY = -(double)y / 250.0;
    }
    

    更常见的方法是使用gluUnProject,请参阅此处NeHe Productions

    void windowToWorld(int windowX, int windowY, GLdouble *worldX, GLdouble *worldY){
        GLint viewport[4];
        GLdouble modelview[16];
        GLdouble projection[16];
        GLfloat winX, winY, winZ;
        GLdouble posZ;
    
        glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
        glGetDoublev(GL_PROJECTION_MATRIX, projection);
        glGetIntegerv(GL_VIEWPORT, viewport);
    
        winX = (GLfloat)windowX;
        winY = (GLfloat)viewport[3] - (float)windowY;
        glReadPixels(windowX, (int)winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);
    
        gluUnProject(winX, winY, winZ, modelview, projection, viewport, worldX, worldY, &posZ);
    }
    

    点击球测试 使用距离公式,这部分非常简单。

    bool isMouseOverBall(float worldClickX, float worldClickY, float ballX, float ballY)
    {
        float distance = sqrt(pow(worldClickX - ballX, 2.0f) + pow(worldClickY - ballY, 2.0f));
        return distance < ballRadius;
    }
    

    <强>最后 你可以看出球是否被点击了。

        GLdouble worldClickX, worldClickY;
        bool clicked;
        windowToWorld(x, y, &worldClickX, &worldClickY);
        clicked = isMouseOverBall(ballX, ballY, worldClickX, worldClickY);
    
    祝你好运!