//============================================================== // Finds next event for sphere i //============================================================== event box::FindNextEvent(int i) { event t = FindNextTransfer(i); event c = FindNextCollision(i); if ((c.time < t.time)&&(c.j == INF)) // next event is check at DBL infinity return c; else if (c.time < t.time) // next event is collision! { CollisionChecker(c); return c; } else // next event is transfer! return t; }
int main() { WORKING_DIR=SDL_GetBasePath(); WORKING_DIR=WORKING_DIR.substr(0,WORKING_DIR.find_last_of("/\\")); WORKING_DIR=WORKING_DIR.substr(0,WORKING_DIR.find_last_of("/\\")); WORKING_DIR=WORKING_DIR.substr(0,WORKING_DIR.find_last_of("/\\")); #ifdef __gnu_linux__ WORKING_DIR+="/"; #elif __WIN32 WORKING_DIR+="\\"; #endif std::cout<< WORKING_DIR<<std::endl; SDL_Window *mainwindow; /* Our window handle */ SDL_GLContext maincontext; /* Our opengl context handle */ Mix_Chunk *pong = NULL; Mix_Chunk *pong2 = NULL; Mix_Chunk *pong3 = NULL; if( SDL_Init( SDL_INIT_VIDEO| SDL_INIT_AUDIO ) < 0 ) { sdldie("SDL could not initialize! SDL Error: %s\n"); } else { //Use OpenGL 3.3 core SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3 ); SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 3 ); SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE ); //Create window mainwindow = SDL_CreateWindow( "pong", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screenWidth, screenHeight, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN |SDL_WINDOW_RESIZABLE ); if( mainwindow == NULL ) { sdldie("Unable to create window"); } else { //Create context maincontext = SDL_GL_CreateContext( mainwindow ); if( maincontext == NULL ){ sdldie("OpenGL context could not be created! SDL Error: %s\n"); } else { //Initialize GLEW glewExperimental = GL_TRUE; GLenum glewError = glewInit(); if( glewError != GLEW_OK ) { std::cout<<"Error initializing GLEW! %s\n"<<glewGetErrorString( glewError ); } //Use Vsync if( SDL_GL_SetSwapInterval( 1 ) < 0 ) { std::cout<<"Warning: Unable to set VSync! SDL Error: %s\n"<<SDL_GetError(); } SDL_DisplayMode current; int should_be_zero = SDL_GetCurrentDisplayMode(0, ¤t); //@HACK:should check for multiple monitors if(should_be_zero != 0) sdldie("Could not get display mode for video display"); screenWidth=(3.0f/4.0f)*current.w; screenHeight=(3.0f/4.0f)*current.h; (*(int*)(&originalScreenHeight))=screenHeight; (*(int*)(&originalScreenWidth))=screenWidth; } } } //Initialize SDL_mixer if( Mix_OpenAudio( 44100, MIX_DEFAULT_FORMAT, 2, 2048 ) < 0 ) { std::cout<<"SDL_mixer could not initialize! SDL_mixer Error: "<<Mix_GetError(); return 1; } //Load sound effects pong = Mix_LoadWAV(WORKING_DIR_FILE("assets/sounds/pong.wav")); if( pong == NULL ) { std::cout<< "Failed to load scratch sound effect! SDL_mixer Error: "<<Mix_GetError(); return 1; } pong2 = Mix_LoadWAV(WORKING_DIR_FILE("assets/sounds/pong2.wav")); if( pong2 == NULL ) { std::cout<< "Failed to load scratch sound effect! SDL_mixer Error: "<<Mix_GetError(); return 1; } pong3 = Mix_LoadWAV(WORKING_DIR_FILE("assets/sounds/pong3.wav")); if( pong3 == NULL ) { std::cout<< "Failed to load scratch sound effect! SDL_mixer Error: "<<Mix_GetError(); return 1; } glEnable(GL_DEPTH_TEST); glViewport(0, 0, screenWidth, screenHeight); /* Clear our buffer with a red background */ glClearColor ( 1.0, 0.0, 0.0, 1.0 ); glClear ( GL_COLOR_BUFFER_BIT ); /* Swap our back buffer to the front */ SDL_GL_SwapWindow(mainwindow); /* Wait 2 seconds */ SDL_Delay(100); /* Same as above, but green */ glClearColor ( 0.0, 1.0, 0.0, 1.0 ); glClear ( GL_COLOR_BUFFER_BIT ); SDL_GL_SwapWindow(mainwindow); SDL_Delay(100); /* Same as above, but blue */ glClearColor ( 0.0, 0.0, 1.0, 1.0 ); glClear ( GL_COLOR_BUFFER_BIT ); SDL_GL_SwapWindow(mainwindow); SDL_Delay(100); GLfloat vertices[] = { 0.5f, 0.5f, 0.0f, // Top Right 0.5f, -0.5f, 0.0f, // Bottom Right -0.5f, -0.5f, 0.0f, // Bottom Left -0.5f, 0.5f, 0.0f, // Top Left }; GLuint indices[] = { // Note that we start from 0! 0, 1, 3, // First Triangle 1, 2, 3 // Second Triangle }; std::vector<Vertex> vertices2; std::vector<GLuint> indices2; { for(unsigned int i=0;i<(sizeof(vertices)/sizeof(vertices[0]));i+=3){ Vertex aux; aux.position={vertices[i+0],vertices[i+1],vertices[i+2]}; vertices2.push_back(aux); } for(unsigned int i=0;i<(sizeof(indices)/sizeof(indices[0]));i++){ indices2.push_back(indices[i]); } } Sprite sprite(vertices2,indices2); GLfloat quadVertices[] = { // Vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates. // Positions // TexCoords -1.0f, 1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f }; // Setup cube VAO GLuint quadVAO, quadVBO; glGenVertexArrays(1, &quadVAO); glGenBuffers(1, &quadVBO); glBindVertexArray(quadVAO); glBindBuffer(GL_ARRAY_BUFFER, quadVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), quadVertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)(2 * sizeof(GLfloat))); glBindVertexArray(0); unsigned int points_p1=0,points_p2=0; bool first_point_p1=true,first_point_p2=true; GameObject player1(&sprite,{0.0f,2.0f}); GameObject player2(&sprite,{0.0f,2.0f}); GameObject ball(&sprite,{0.0f,0.0f}); Entity roof(&sprite); Entity floor(&sprite); GameObject leftwall(&sprite,{0.0f,0.0f}); GameObject rightwall(&sprite,{0.0f,0.0f}); { player1.entity.setPos({-0.95f,0.0f}); player2.entity.setPos({0.95f,0.0f}); ball.entity.setPos({0.0f,8.0f}); roof.setPos({-1.0f,1.10f}); floor.setPos({-1.0f,-1.10f}); roof.scale({4.0f,1.0f}); floor.scale({4.0f,1.0f}); leftwall.entity.setPos({-1.0f,0.0f}); rightwall.entity.setPos({1.0f,0.0f}); leftwall.entity.scale({0.025f,2.0f}); rightwall.entity.scale({0.025f,2.0f}); player1.entity.scale({0.025f, 0.49f}); player2.entity.scale({0.025f, 0.49f}); ball.entity.scale({0.0625f,0.0625f}); ball.entity.order(SCALE,ROTATE,TRANSLATE); } std::vector<CollisionChecker> collisions; { collisions.push_back(CollisionChecker(&player1.entity,&roof)); collisions.push_back(CollisionChecker(&player1.entity,&floor)); collisions.push_back(CollisionChecker(&player2.entity,&roof)); collisions.push_back(CollisionChecker(&player2.entity,&floor)); } CollisionChecker ball_floor(&ball.entity,&floor); CollisionChecker ball_roof(&ball.entity,&roof); CollisionChecker ball_p1(&ball.entity,&player1.entity); CollisionChecker ball_p2(&ball.entity,&player2.entity); CollisionChecker ball_leftwall(&ball.entity,&leftwall.entity); CollisionChecker ball_rightwall(&ball.entity,&rightwall.entity); SDL_StartTextInput(); bool quit = false; bool started=false; glm::vec2 p1_speed_gain(0.0f,0.0f); glm::vec2 p2_speed_gain(0.0f,0.0f); unsigned int i=0; Uint32 lastFrame=0; Uint32 deltaTime=0; float framerate=0.0f; float dt; framebuffer fb(originalScreenWidth,originalScreenHeight); Shader shader(WORKING_DIR_FILE("assets/shaders/shader.vert"),WORKING_DIR_FILE("assets/shaders/shader.frag")); Shader fb_shader(WORKING_DIR_FILE("assets/shaders/framebuffer_shader.vert"),WORKING_DIR_FILE("assets/shaders/framebuffer_shader.frag")); while(!quit) { SDL_PumpEvents(); Uint32 currentFrame = SDL_GetTicks();//miliseconds deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; dt = deltaTime/1000.0f; framerate += 1000.0f/deltaTime; p1_speed_gain={0.0f,0.0f}; p2_speed_gain={0.0f,0.0f}; { const Uint8 *keystates = SDL_GetKeyboardState( NULL ); quit = keystates[SDL_GetScancodeFromKey(SDLK_q)] || SDL_QuitRequested(); started = started || keystates[SDL_GetScancodeFromKey(SDLK_SPACE)]; if(started){ if(keystates[SDL_GetScancodeFromKey(SDLK_w )]) { player1.move( dt ); p1_speed_gain={ 0.0f , 1.0f }; } if(keystates[SDL_GetScancodeFromKey(SDLK_s )]) { player1.move(-dt ); p1_speed_gain={ 0.0f ,-1.0f }; } if(keystates[SDL_GetScancodeFromKey(SDLK_UP )]) { player2.move( dt ); p2_speed_gain={ 0.0f , 1.0f }; } if(keystates[SDL_GetScancodeFromKey(SDLK_DOWN)]) { player2.move(-dt ); p2_speed_gain={ 0.0f ,-1.0f }; } if(keystates[SDL_GetScancodeFromKey(SDLK_j)]) { player1.entity.rotate(15.0f ); } do_ball_movement(ball,dt); } } { unsigned int size=collisions.size(); for(unsigned int i=0;i<size;i++) { if(collisions[i].checkCollision()) handleCollision(collisions[i]); } } { glm::vec3 pos=ball.entity.position; glm::vec3 oldpos=ball.entity.oldPosition; if(ball_floor.checkCollision()){ handleCollision(ball_floor); ball.speed=glm::normalize(glm::reflect(glm::vec2(pos.x-oldpos.x,pos.y-oldpos.y),glm::vec2(0.0f,1.0f)))*glm::length(ball.speed); Mix_PlayChannel( -1, pong2, 0 ); } if(ball_roof.checkCollision()){ handleCollision(ball_roof); ball.speed=glm::normalize(glm::reflect(glm::vec2(pos.x-oldpos.x,pos.y-oldpos.y),glm::vec2(0.0f,-1.0f)))*glm::length(ball.speed); Mix_PlayChannel( -1, pong2, 0 ); } if(ball_p1.checkCollision()){ handleCollision(ball_p1); ball.speed=glm::normalize(glm::reflect(glm::vec2(pos.x-oldpos.x,pos.y-oldpos.y),glm::vec2(1.0f,0.0f)) + p1_speed_gain) * (glm::length(ball.speed)+glm::length(p1_speed_gain)); Mix_PlayChannel( -1, pong, 0 ); } if(ball_p2.checkCollision()){ handleCollision(ball_p2); ball.speed=glm::normalize(glm::reflect(glm::vec2(pos.x-oldpos.x,pos.y-oldpos.y),glm::vec2(-1.0f,0.0f)) + p2_speed_gain) * (glm::length(ball.speed)+glm::length(p2_speed_gain)); Mix_PlayChannel( -1, pong, 0 ); } if(ball_leftwall.checkCollision()){ points_p2++; ball.entity.setPos({0.0f,8.0f});//scale adjusted due the order it uses... ball.speed={0.0f,0.0f}; Mix_PlayChannel( -1, pong3, 0 ); } if(ball_rightwall.checkCollision()){ points_p1++; ball.entity.setPos({0.0f,8.0f}); ball.speed={0.0f,0.0f}; Mix_PlayChannel( -1, pong3, 0 ); } if(((ball.speed.y/ball.speed.x)>3.0f) || ((ball.speed.y/ball.speed.x)<-3.0f)){ ball.speed.y/=2.0f; ball.speed.x*=4.0f; } } if(i==100){ i=0; framerate/=100.0f; std::cout<<framerate<<std::endl; std::cout<<points_p1<<'-'<<points_p2<<std::endl; framerate=0.0f; } i+=1; shader.Use(); fb.bind(); glViewport(0,0,originalScreenWidth,originalScreenHeight); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glEnable(GL_DEPTH_TEST); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glm::mat4 projection;//= glm::ortho(-1.0f,1.0f,-1.0f,1.0f,0.0f,1.0f); GLint projection_uniform=glGetUniformLocation(shader.Program, "projection"); glUniformMatrix4fv(projection_uniform, 1, GL_FALSE, glm::value_ptr(projection)); glm::vec2 position; position=glm::vec2(-3.0f*1.06255f*0.125f,0.0f); if(points_p1>=5 || points_p2>=5){ drawdigit(-1,&shader,position,{0.125f,0.125f},DIGIT_TOP|DIGIT_MIDDLE|DIGIT_TOPLEFT|DIGIT_TOPRIGHT|DIGIT_BOTTOMLEFT); position+=glm::vec2(1.0625f*0.125f,0.0f); drawdigit((points_p1>=5)?1:2,&shader,position,{0.125f,0.125f}); position+=glm::vec2(1.0625f*0.125f,0.0f); position+=glm::vec2(1.0625f*0.125f,0.0f); drawdigit(-1,&shader,position,{0.125f,0.125f},DIGIT_TOPLEFT |DIGIT_BOTTOMLEFT |DIGIT_BOTTOMLEFT_MIDDLE| DIGIT_TOPRIGHT|DIGIT_BOTTOMRIGHT|DIGIT_BOTTOMRIGHT_MIDDLE); position+=glm::vec2(1.0625f*0.125f,0.0f); drawdigit(-1,&shader,position,{0.125f,0.125f},DIGIT_TOPMIDDLE|DIGIT_BOTTOMMIDDLE); position+=glm::vec2(1.0625f*0.125f,0.0f); drawdigit(-1,&shader,position,{0.125f,0.125f},DIGIT_BOTTOMLEFT |DIGIT_TOPLEFT|DIGIT_TOPLEFT_BOTTOMRIGHT| DIGIT_BOTTOMRIGHT|DIGIT_TOPRIGHT); position+=glm::vec2(1.0625f*0.125f,0.0f); drawdigit(5,&shader,position,{0.125f,0.125f}); started=false; } player1.entity.draw(&shader); player2.entity.draw(&shader); if(started) ball.entity.draw(&shader); roof.draw(&shader); floor.draw(&shader); leftwall.entity.draw(&shader); rightwall.entity.draw(&shader); unsigned int aux=points_p2; position=glm::vec2(0.25f,0.5f); //NOTE: when one of the points hits 20 I should put a you win screen first_point_p2=points_p2? false:true; while((aux/10) || (aux%10) || first_point_p2){ drawdigit(aux%10,&shader,position,{0.125f,0.125f}); position.x-=1.5f*0.125f; aux=aux/10; first_point_p2=false;//endless loop if I dont } aux=points_p1; position={-0.25f,0.5f}; first_point_p1=points_p1? false:true; while((aux/10) || (aux%10) || first_point_p1){ drawdigit(aux%10,&shader,position,{0.125f,0.125f}); position.x-=1.5f*0.125f; aux=aux/10; first_point_p1=false; } fb.unbind(); SDL_GetWindowSize(mainwindow,&screenWidth,&screenHeight); glViewport(0,0,screenWidth,screenHeight); glClearColor(0.0f, 0.0f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glDisable(GL_DEPTH_TEST); fb_shader.Use(); glm::mat4 screenscaler; float aspectRatio=(float)screenWidth/(float)screenHeight; float inverseAspectRatio=(float)screenHeight/(float)screenWidth; if(aspectRatio>1.0f) screenscaler = glm::perspective(radians(59.2f),aspectRatio,0.1f,1.0f); else screenscaler = glm::perspective(radians(59.2f),inverseAspectRatio,0.1f,1.0f); GLint model_uniform=glGetUniformLocation(fb_shader.Program, "model"); glUniformMatrix4fv(model_uniform, 1, GL_FALSE, glm::value_ptr(screenscaler)); glBindVertexArray(quadVAO);//should scale the scale to the % of resolution glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, fb.texture); glDrawArrays(GL_TRIANGLES, 0, 6); glBindTexture(GL_TEXTURE_2D,0); glBindVertexArray(0); SDL_Delay(1); SDL_GL_SwapWindow(mainwindow); if(points_p1>=5 || points_p2>=5){ points_p1=0; points_p2=0; ball.speed={0.0f,0.0f}; SDL_Delay(3000); } } DESTRUCTOR(fb); DESTRUCTOR(shader); DESTRUCTOR(fb_shader); Mix_FreeChunk(pong); Mix_FreeChunk(pong2); Mix_FreeChunk(pong3); SDL_GL_DeleteContext(maincontext); SDL_DestroyWindow(mainwindow); SDL_Quit(); return 0; }