【OpenGL】水果忍者的刀锋模拟程序

本文详细介绍了如何利用OpenGL编程实现水果忍者游戏中刀锋切割水果的效果。通过C++类的设计,结合OpenGL图形库,讲解了从基本的几何形状创建到刀刃动画的实现过程,包括函数的调用和渲染技术的应用。
摘要由CSDN通过智能技术生成
学习OpenGL的一个好玩程序,没想到它的功能那么厉害,有三个文件,虽然不是本人原创,是大神分享的,在这里给大家分享一下

#ifndef _BLADE_H_  
#define _BLADE_H_  
  
#include 
  
  
   
     
#include 
   
   
    
      
  
class Blade  
{  
public :  
    int winWidth, winHeight;  
    GLint mousePosX, mousePosY;  
  
    Blade();  
    ~Blade();  
  
    void drawBlade(void );  
    void sampleFadeBlade(void);  
    void mouse2BladeState(int btn, int state, int x, int y);  
  
    void recordOrthoData(GLfloat left, GLfloat right, GLfloat bottom, GLfloat up);  
  
private :  
    static const int MAXTIMER = 10;  
    static const int vertexArrHead = 0;  
    static const int vertexArrTail = 20;  
    static const int POINTTHRESHOLD = 16;  
    static const GLint sampleTimerFlag = 0;  
    static const GLint fadeTimerFlag = 1;  
  
    int vertexArrStartPos;  
    //int vertexArrEndPos;  
  
    GLint pointCount;  
    GLint drawFlag;  
    GLint mouseDownFlag;      
    GLfloat bodyVertex[vertexArrTail][2];  
    GLfloat uniformSideVertex[vertexArrTail][2][2];  
    GLfloat outerSideVertex[vertexArrTail][2][2];  
    GLfloat innerSideVertex[vertexArrTail][2][2];  
    GLfloat bladeThreshold;  
  
    clock_t start[MAXTIMER], finish[MAXTIMER];  
    GLfloat sampleInterval;  
    GLfloat fadeInterval;  
  
    GLfloat orthoLeft;  
    GLfloat orthoRight;  
    GLfloat orthoBottom;  
    GLfloat orthoUp;  
  
    void init(void);  
    void calcSideVertex(GLfloat *startVertex, GLfloat *endVertex, GLfloat returnSideVertex[][2], GLfloat sideWidth, GLfloat end2StartRatio);  
    void vertexSampling();  
    GLint isTimeUp(GLint timerFlag, GLfloat timeInterval);  
    void vertexFading(void );  
    void recalculateBladeWidth(void );  
};  
  
#endif  
   
   
  
  

#include "stdafx.h"
#include "Blade.h"  
#include 
   
   
    
      
#include 
    
    
     
       
//#include 
     
     
      
        
#include 
      
      
       
          
//#include 
       
       
         Blade::Blade() { winWidth = 0; winHeight = 0; mousePosX = 0; mousePosY = 0; vertexArrStartPos = 0; //vertexArrEndPos = 0; pointCount = 0; drawFlag = 0; mouseDownFlag = 0; sampleInterval = 0.015f; fadeInterval = 0.02f; bladeThreshold = 0.032f; init(); } Blade::~Blade() {} void Blade::calcSideVertex(GLfloat *startVertex, GLfloat *endVertex, GLfloat returnSideVertex[][2], GLfloat sideWidth, GLfloat end2StartRatio) { GLfloat tmpAngle = 0.0; GLfloat tmpVertex[2] = {0.0f, 0.0f}; GLfloat tmpSideVertex[2][2] = {{0.0f, 0.0f}, {0.0f, 0.0f}}; GLfloat tmpResult = 0.0; tmpAngle = atan((endVertex[1] - startVertex[1])/(endVertex[0] - startVertex[0])); tmpVertex[0] = endVertex[0]-(endVertex[0]-startVertex[0])*end2StartRatio; tmpVertex[1] = endVertex[1]-(endVertex[1]-startVertex[1])*end2StartRatio; if (endVertex[0] > startVertex[0]) { tmpSideVertex[0][0] = tmpVertex[0] + (sideWidth * sin(tmpAngle)); tmpSideVertex[0][1] = tmpVertex[1] - (sideWidth * cos(tmpAngle)); tmpSideVertex[1][0] = tmpVertex[0] - (sideWidth * sin(tmpAngle)); tmpSideVertex[1][1] = tmpVertex[1] + (sideWidth * cos(tmpAngle)); } else { tmpSideVertex[0][0] = tmpVertex[0] - (sideWidth * sin(tmpAngle)); tmpSideVertex[0][1] = tmpVertex[1] + (sideWidth * cos(tmpAngle)); tmpSideVertex[1][0] = tmpVertex[0] + (sideWidth * sin(tmpAngle)); tmpSideVertex[1][1] = tmpVertex[1] - (sideWidth * cos(tmpAngle)); } //判断点在向量的左边还是右边 tmpResult = (startVertex[0] - tmpSideVertex[0][0])*(endVertex[1] - tmpSideVertex[0][1]) - (startVertex[1] - tmpSideVertex[0][1])*(endVertex[0] - tmpSideVertex[0][0]); if (tmpResult > 0.0f) { returnSideVertex[0][0] = tmpSideVertex[1][0]; returnSideVertex[0][1] = tmpSideVertex[1][1]; returnSideVertex[1][0] = tmpSideVertex[0][0]; returnSideVertex[1][1] = tmpSideVertex[0][1]; } else { returnSideVertex[0][0] = tmpSideVertex[0][0]; returnSideVertex[0][1] = tmpSideVertex[0][1]; returnSideVertex[1][0] = tmpSideVertex[1][0]; returnSideVertex[1][1] = tmpSideVertex[1][1]; } } void Blade::init(void) { int i = 0; for (i = 0; i < vertexArrTail; i++) { bodyVertex[i][0] = 0.0f; bodyVertex[i][1] = 0.0f; uniformSideVertex[i][0][0] = 0.0f; uniformSideVertex[i][0][1] = 0.0f; uniformSideVertex[i][1][0] = 0.0f; uniformSideVertex[i][1][1] = 0.0f; outerSideVertex[i][0][0] = 0.0f; outerSideVertex[i][0][1] = 0.0f; outerSideVertex[i][1][0] = 0.0f; outerSideVertex[i][1][1] = 0.0f; innerSideVertex[i][0][0] = 0.0f; innerSideVertex[i][0][1] = 0.0f; innerSideVertex[i][1][0] = 0.0f; innerSideVertex[i][1][1] = 0.0f; } } void Blade::vertexSampling() { int tmpIndex1 = 0, tmpIndex2 = 0; GLfloat uniformX = 0.0f, uniformY = 0.0f; GLfloat realX = 0.0f, realY = 0.0f; drawFlag = 0; pointCount++; uniformX = (GLfloat)mousePosX / (GLfloat)winWidth; uniformY = (GLfloat)(winHeight - mousePosY) / (GLfloat)winHeight; realX = uniformX*(orthoRight - orthoLeft) + orthoLeft; realY = uniformY*(orthoUp - orthoBottom) + orthoBottom; if (pointCount == 0) { bodyVertex[vertexArrStartPos][0] = realX; bodyVertex[vertexArrStartPos][1] = realY; } else { tmpIndex1 = (vertexArrStartPos + pointCount - 1)%vertexArrTail; tmpIndex2 = (tmpIndex1 + 1)%vertexArrTail; bodyVertex[tmpIndex2][0] = realX; bodyVertex[tmpIndex2][1] = realY; calcSideVertex(bodyVertex[tmpIndex1], bodyVertex[tmpIndex2], uniformSideVertex[tmpIndex2], bladeThreshold, 0.4); } if (pointCount >= 3) drawFlag = 1; //vertexArrEndPos++; //if (vertexArrEndPos >= vertexArrTail) // vertexArrEndPos -= vertexArrTail; } GLint Blade::isTimeUp(GLint timerFlag, GLfloat timeInterval) { double duration = 0.0; finish[timerFlag] = clock(); duration = (double)(finish[timerFlag] - start[timerFlag]) / CLOCKS_PER_SEC; if (duration >= timeInterval) { start[timerFlag] = clock(); return 1; } return 0; } void Blade::vertexFading() { vertexArrStartPos++; if (vertexArrStartPos >= vertexArrTail) vertexArrStartPos -= vertexArrTail; pointCount--; if (pointCount <= 2) drawFlag = 0; } void Blade::recalculateBladeWidth(void ) { int i = 0; int tmpIndex = 0; GLfloat ratio = 0.0f; GLfloat tmp[4] = {0.0f, 0.0f, 0.0f, 0.0f}; //reclaculate the blade width for (i = 1; i < pointCount - 1; i++) { tmpIndex = (vertexArrStartPos + i)%vertexArrTail; tmp[0] = uniformSideVertex[tmpIndex][0][0] + uniformSideVertex[tmpIndex][1][0]; tmp[1] = uniformSideVertex[tmpIndex][0][0] - uniformSideVertex[tmpIndex][1][0]; tmp[2] = uniformSideVertex[tmpIndex][0][1] + uniformSideVertex[tmpIndex][1][1]; tmp[3] = uniformSideVertex[tmpIndex][0][1] - uniformSideVertex[tmpIndex][1][1]; if (i == (pointCount-2)) ratio = 1.0; else ratio = (GLfloat)i/(GLfloat)pointCount; outerSideVertex[tmpIndex][0][0] = 0.5*(tmp[0] + ratio*tmp[1]); outerSideVertex[tmpIndex][0][1] = 0.5*(tmp[2] + ratio*tmp[3]); outerSideVertex[tmpIndex][1][0] = 0.5*(tmp[0] - ratio*tmp[1]); outerSideVertex[tmpIndex][1][1] = 0.5*(tmp[2] - ratio*tmp[3]); innerSideVertex[tmpIndex][0][0] = 0.5*(tmp[0] + ratio*2.0/3.0*tmp[1]); innerSideVertex[tmpIndex][0][1] = 0.5*(tmp[2] + ratio*2.0/3.0*tmp[3]); innerSideVertex[tmpIndex][1][0] = 0.5*(tmp[0] - ratio*2.0/3.0*tmp[1]); innerSideVertex[tmpIndex][1][1] = 0.5*(tmp[2] - ratio*2.0/3.0*tmp[3]); } } void Blade::drawBlade() { int i = 0; //printf("%d\n", pointCount); //printf("%d\n", vertexArrStartPos); //printf("Flag:%d\n\n", drawFlag); if (drawFlag == 0){ return; } /*****--------------------------------------*****/ //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); //glPolygonMode(GL_FRONT, GL_LINE); /*****--------------------------------------*****/ //draw the outer blade glColor4f(0.2f, 0.2f, 0.9f, 0.5f); glBegin(GL_POLYGON); glVertex2fv(bodyVertex[vertexArrStartPos]); glVertex2fv(outerSideVertex[(vertexArrStartPos+1)%vertexArrTail][0]); glVertex2fv(outerSideVertex[(vertexArrStartPos+1)%vertexArrTail][1]); glEnd(); for (i = 1; i < pointCount - 2; i++) { glBegin(GL_POLYGON); glVertex2fv(outerSideVertex[(vertexArrStartPos + i)%vertexArrTail][0]); glVertex2fv(outerSideVertex[(vertexArrStartPos + i + 1)%vertexArrTail][0]); glVertex2fv(outerSideVertex[(vertexArrStartPos + i)%vertexArrTail][1]); glEnd(); glBegin(GL_POLYGON); glVertex2fv(outerSideVertex[(vertexArrStartPos + i + 1)%vertexArrTail][1]); glVertex2fv(outerSideVertex[(vertexArrStartPos + i)%vertexArrTail][1]); glVertex2fv(outerSideVertex[(vertexArrStartPos + i + 1)%vertexArrTail][0]); glEnd(); } glBegin(GL_POLYGON); glVertex2fv(outerSideVertex[(vertexArrStartPos + pointCount - 2)%vertexArrTail][0]); glVertex2fv(bodyVertex[(vertexArrStartPos + pointCount - 1)%vertexArrTail]); glVertex2fv(outerSideVertex[(vertexArrStartPos + pointCount - 2)%vertexArrTail][1]); glEnd(); //draw the inner blade glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glBegin(GL_POLYGON); glVertex2fv(bodyVertex[vertexArrStartPos]); glVertex2fv(innerSideVertex[(vertexArrStartPos+1)%vertexArrTail][0]); glVertex2fv(innerSideVertex[(vertexArrStartPos+1)%vertexArrTail][1]); glEnd(); for (i = 1; i < pointCount - 2; i++) { glBegin(GL_POLYGON); glVertex2fv(innerSideVertex[(vertexArrStartPos + i)%vertexArrTail][0]); glVertex2fv(innerSideVertex[(vertexArrStartPos + i + 1)%vertexArrTail][0]); glVertex2fv(innerSideVertex[(vertexArrStartPos + i)%vertexArrTail][1]); glEnd(); glBegin(GL_POLYGON); glVertex2fv(innerSideVertex[(vertexArrStartPos + i + 1)%vertexArrTail][1]); glVertex2fv(innerSideVertex[(vertexArrStartPos + i)%vertexArrTail][1]); glVertex2fv(innerSideVertex[(vertexArrStartPos + i + 1)%vertexArrTail][0]); glEnd(); } glBegin(GL_POLYGON); glVertex2fv(innerSideVertex[(vertexArrStartPos + pointCount - 2)%vertexArrTail][0]); glVertex2fv(bodyVertex[(vertexArrStartPos + pointCount - 1)%vertexArrTail]); glVertex2fv(innerSideVertex[(vertexArrStartPos + pointCount - 2)%vertexArrTail][1]); glEnd(); } void Blade::sampleFadeBlade(void) { if (mouseDownFlag == 1) { sampleInterval = (pointCount <= 2 ? 0.005 : 0.015); if (isTimeUp(sampleTimerFlag, sampleInterval) == 1) { vertexSampling(); recalculateBladeWidth(); glutPostRedisplay(); } } if (pointCount > 0) { fadeInterval = (pointCount >= POINTTHRESHOLD ? 0.0 : 0.016); fadeInterval = (mouseDownFlag == 0 ? 0.0 : fadeInterval); //printf("%f\n", fadeInterval); if (isTimeUp(fadeTimerFlag, fadeInterval) == 1) { vertexFading(); recalculateBladeWidth(); glutPostRedisplay(); } } } void Blade::mouse2BladeState(int btn, int state, int x, int y) { if (btn == GLUT_LEFT_BUTTON) { if (state == GLUT_DOWN) { mousePosX = x; mousePosY = y; mouseDownFlag = 1; start[sampleTimerFlag] = clock(); start[fadeTimerFlag] = clock(); pointCount = 0; } else if (state == GLUT_UP) { mouseDownFlag = 0; } } } void Blade::recordOrthoData(GLfloat left, GLfloat right, GLfloat bottom, GLfloat up) { orthoLeft = left; orthoRight = right; orthoBottom = bottom; orthoUp = up; } 
       
      
      
     
     
    
    
   
   
#include "stdafx.h"
#include 
    
    
     
       
#include 
     
     
      
        
#include "Blade.h"  
  
#ifndef _LINUX_  
#include 
      
      
       
         
void mySleep(int millisecond) {Sleep(millisecond);};  
#else  
#include 
       
       
        
          
void mySleep(int millisecond) {sleep((float)millisecond/1000.0);};  
#endif  
  
Blade myBlade;  
  
const int sleepTime = 1;  
  
void display(void )  
{  
    glClearColor(0.3f, 0.3f, 0.3f, 1.0f);  
    glClear(GL_COLOR_BUFFER_BIT);  
  
    myBlade.drawBlade();  
  
    glutSwapBuffers();  
}  
  
void mouseButton(int btn, int state, int x, int y)  
{  
    myBlade.mouse2BladeState(btn, state, x, y);  
    //if (btn == GLUT_RIGHT_BUTTON)  
    //    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);  
}  
  
void reshape(int w, int h)  
{  
    myBlade.winWidth = w;  
    myBlade.winHeight = h;  
}  
  
void mouseMove(int x, int y)  
{  
    myBlade.mousePosX = x;  
    myBlade.mousePosY = y;  
}  
  
void idle(void)  
{  
    mySleep(sleepTime);  
  
    myBlade.sampleFadeBlade();  
}  
int main(int argc, char *argv[])  
{  
    glutInit(&argc, argv);  
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);  
    glutInitWindowPosition(100, 100);  
    glutInitWindowSize(800, 600);  
    glutCreateWindow("Ninjia blade");  
  
    gluOrtho2D(0.0f, 1.0f, 0.0f, 1.0f);  
    myBlade.recordOrthoData(0.0f, 1.0f, 0.0f, 1.0f);  
    //gluOrtho2D(0.0f, -1.0f, -2.0f, 1.0f);  
    //myBlade.recordOrthoData(0.0f, -1.0f, -2.0f, 1.0f);  
    glEnable(GL_LINE_SMOOTH);  
  
    glEnable(GL_CULL_FACE);  
    glFrontFace(GL_CCW);  
  
    glutDisplayFunc(&display);  
    glutMouseFunc(&mouseButton);  
    glutReshapeFunc(&reshape);  
    glutMotionFunc(&mouseMove);  
    glutIdleFunc(&idle);  
  
    glutMainLoop();  
    return 0;  
}  
       
       
      
      
     
     
    
    


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值