Tennis Anime — программа на OpenGL для моделирования игры в теннис

Tennis Anime —  программа, которая анимирует процесс игры в теннис. Программа реализована на графической библиотеке OpenGL на платформе Win32. Есть возможность управления движения видовым экраном в пространстве с помощью стрелок Вверх, Вниз, Влево, Направо. Написан на C++ в среде Visual Studio 2010. Основной целью данной программы является демонстрация движения мяча в воздухе и движение ракеток.

tennis-anime

Для создания временных интервалов движения мяча в программе используется таймер. Движение мяча в пространстве от ракетки описывается формулой горизонтально брошенного тела, а отскок от земли — формулой движения тела под углом.

Стартовый код OpenGL /Win32

Часто бывает, особенно у новичков, что когда-то занимались на OpenGL, но забыли как написать начальный код для OpenGL приложения. Ниже представлен шаблонный код для дальнейшего развертывания графической библиотеки OpenGL. Конечно, Win32— приложения сейчас используются не столь популярностью, как раньше, но на на Win32 до сих учатся и программируют в учебных целях. Особенностью работы с OpenGL в Win32 является простота.

Легче, при разрастании кода, разделить главный исходный файл на несколько файлов с заголовками, чтобы не путаться в одном большом коде, как говориться : «Разделяй и властвуй!» :).

/*
*WebSofter MG
*/

#include <windows.h>
#include <math.h>

#include <gl/gl.h>
#include <gl/glu.h>

#include "glut.h"
#include "glaux.h"

#pragma comment(lib, "glut32.lib")//Подключаем библиотеку Glut
#pragma comment(lib, "Glaux.lib")//Подключаем библиотеку Glaux

HWND hWnd;
HGLRC hGLRC;
HDC hDC;



int SetWindowPixelFormat()
{
    int m_GLPixelIndex;
    PIXELFORMATDESCRIPTOR pfd;


    pfd.nSize       = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion    = 1;

    pfd.dwFlags   = PFD_DRAW_TO_WINDOW | 
                    PFD_SUPPORT_OPENGL | 
                    PFD_DOUBLEBUFFER;

    pfd.iPixelType     = PFD_TYPE_RGBA;
    pfd.cColorBits     = 32;
    pfd.cRedBits       = 8;
    pfd.cRedShift      = 16;
    pfd.cGreenBits     = 8;
    pfd.cGreenShift    = 8;
    pfd.cBlueBits      = 8;
    pfd.cBlueShift     = 0;
    pfd.cAlphaBits     = 0;
    pfd.cAlphaShift    = 0;
    pfd.cAccumBits     = 64;    
    pfd.cAccumRedBits  = 16;
    pfd.cAccumGreenBits   = 16;
    pfd.cAccumBlueBits    = 16;
    pfd.cAccumAlphaBits   = 0;
    pfd.cDepthBits        = 32;
    pfd.cStencilBits      = 8;
    pfd.cAuxBuffers       = 0;
    pfd.iLayerType        = PFD_MAIN_PLANE;
    pfd.bReserved         = 0;
    pfd.dwLayerMask       = 0;
    pfd.dwVisibleMask     = 0;
    pfd.dwDamageMask      = 0;



    m_GLPixelIndex = ChoosePixelFormat( hDC, &pfd);
    if(m_GLPixelIndex==0) // Let's choose a default index.
    {
     m_GLPixelIndex = 1;    
     if(DescribePixelFormat(hDC,m_GLPixelIndex,sizeof(PIXELFORMATDESCRIPTOR),&pfd)==0)
       return 0;
    }


    if (SetPixelFormat( hDC, m_GLPixelIndex, &pfd)==FALSE)
        return 0;


    return 1;
}




void resize(int width,int height)
{
    glViewport(0,0,width,height);
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    glOrtho(-5,5, -5,5, 2,12);    
    gluLookAt( 0,0,5, 0,0,0, 0,1,0 );
    glMatrixMode( GL_MODELVIEW );
}    

int DrawGLScene(GLvoid)//Здесь будет весь код OpenGL объектов
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
	glTranslatef(0.0,0.0,1.0);//Настраиваем координаты	

	glPushMatrix();
	  auxSolidSphere(2.5f);//Выводим сферу
        glPopMatrix();

	return TRUE;
}


void display()
{
  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

  	/* remove next tree lines
	 * and enter your code here
	 */
     DrawGLScene();

  glFinish();
  SwapBuffers(wglGetCurrentDC());
}




LRESULT CALLBACK WindowFunc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
float pos[4] = {3,3,3,1};
float dir[3] = {-1,-1,-1};
PAINTSTRUCT ps;

switch(msg)
	{

	case WM_CREATE:
	hDC = GetDC(hWnd);
	SetWindowPixelFormat();
	hGLRC = wglCreateContext(hDC);
	wglMakeCurrent(hDC, hGLRC);

    glEnable(GL_ALPHA_TEST);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_COLOR_MATERIAL);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glLightfv(GL_LIGHT0, GL_POSITION, pos);
    glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, dir);

        break; 

    
	case WM_DESTROY:
	if (hGLRC) 
	{
	    wglMakeCurrent(NULL, NULL);
	    wglDeleteContext(hGLRC);
	}
	ReleaseDC(hWnd, hDC);
	PostQuitMessage(0);
	break;

	
	
	case WM_PAINT:
	BeginPaint(hWnd, &ps);
	display();
	EndPaint(hWnd, &ps);
	break;
	

    
	case WM_SIZE:
	resize( LOWORD(lParam), HIWORD(lParam) );
	break;  


       default:
	return DefWindowProc(hWnd,msg,wParam,lParam);
	}

return 0;
}




int WINAPI WinMain(HINSTANCE hThisInst,
				   HINSTANCE hPrevInst,
				   LPSTR str,int nWinMode)
{
MSG msg;
WNDCLASS wcl;


wcl.hInstance=hThisInst;
wcl.lpszClassName = L"OpenGLWinClass";
wcl.lpfnWndProc = WindowFunc;
wcl.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;

wcl.hIcon = NULL;
wcl.hCursor = LoadCursor(NULL,IDC_ARROW);
wcl.lpszMenuName = NULL;

wcl.cbClsExtra = 0;
wcl.cbWndExtra = 0;

wcl.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
RegisterClass(&wcl);


hWnd = CreateWindow(L"OpenGLWinClass", L"Win API Template", 
					 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
					 200,
					 150,
					 400,
					 420,
					 HWND_DESKTOP, NULL,
					 hThisInst, NULL);


ShowWindow(hWnd,nWinMode);
UpdateWindow(hWnd);


while(1)
{
  while( PeekMessage(&msg,NULL,0,0,PM_NOREMOVE) ) 
    if(GetMessage(&msg,NULL,0,0))
     { 
      TranslateMessage(&msg);
      DispatchMessage(&msg);
     }
    else
      return 0;

  display();
} 


return 0;
}

Вы можете работать со стандартными библиотеками OpenGl, это:

#include <gl/gl.h>
#include <gl/glu.h>

а можете подключить и дополнительные библиотеки, на подобие:

#include "glut.h"
#include "glaux.h"
#pragma comment(lib, "glut32.lib")//Подключаем библиотеку Glut
#pragma comment(lib, "Glaux.lib")//Подключаем библиотеку Glaux

Чтобы подключить их, вам нужно скачать последние версии glut32.lib/glut.h и glaux.lib/glaux.h и закинуть их в ту же директорию, где ваш файл запуска главной функции WinMain, т.е. вышеприведенный.