OpenGl在tile map C ++上绘制

时间:2016-01-26 00:18:25

标签: c++ opengl glut texture-mapping freeglut

我是OpenGL的新手。我从我遵循的教程中使用了以下代码,它的作用是渲染一个tile map。它成功地完成了这个,但我现在的问题是我想在窗口上添加一个可移动的对象,但它没有出现。

#include "stdafx.h"

#include <string> 
#include <windows.h> 
#include <iostream> 
#include <conio.h> 
#include <sstream>  
#include <math.h>  
#include <gl\gl.h> 
#include <gl\glu.h> 
#include "GL/freeglut.h" 
#pragma comment(lib, "OpenGL32.lib")


// window size and update rate (60 fps) 
int width = 700; 
int height = 700; 
int interval = 1000 / 60; 


// ball 
float ball_pos_x = width / 2; 
float ball_pos_y = height / 2; 
float ball_dir_x = -1.0f; 
float ball_dir_y = 0.0f; 
int ball_width = 20;
int ball_height = 20;
int ball_speed = 5;

GLuint texture; //the array for our texture
GLuint texture2; //the array for our second texture

void keyboard() {    

    if (GetAsyncKeyState(VK_LEFT)) ball_pos_x -= ball_speed;    
    if (GetAsyncKeyState(VK_RIGHT)) ball_pos_x += ball_speed;
    if (GetAsyncKeyState(VK_UP)) ball_pos_y += ball_speed;    
    if (GetAsyncKeyState(VK_DOWN)) ball_pos_y -= ball_speed;
}


int cMap[30][30] = { //our map
    {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
    {1, 0, 1, 0, 0, 0, 0, 0, 0, 1},
    {1, 0, 1, 0, 0, 0, 0, 0, 0, 1},
    {1, 0, 1, 0, 0, 0, 0, 0, 0, 1},
    {1, 0, 1, 0, 0, 0, 0, 0, 0, 1},
    {1, 0, 1, 1, 1, 1, 1, 1, 1, 1},
    {1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
    {1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
    {1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
    {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
};

void drawRect(float x, float y, float width, float height) {    
    glBegin(GL_QUADS);        
    glVertex2f(x, y);        
    glVertex2f(x + width, y);        
    glVertex2f(x + width, y + height);        
    glVertex2f(x, y + height);    
    glEnd(); 
}


GLuint LoadTexture( const char * filename, int width, int height )
{
    GLuint texture;
    unsigned char * data;
    FILE * file;

    //The following code will read in our RAW file
    file = fopen( filename, "rb" );
    if ( file == NULL ) return 0;
    data = (unsigned char *)malloc( width * height * 3 );
    fread( data, width * height * 3, 1, file );
    fclose( file );

    glGenTextures( 1, &texture );
    glBindTexture( GL_TEXTURE_2D, texture );
    glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, 
GL_MODULATE ); //set texture environment parameters

    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 
GL_LINEAR );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_LINEAR );

    //Here we are setting the parameter to repeat the texture 
//instead of clamping the texture
    //to the edge of our shape. 
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 
GL_REPEAT );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 
GL_REPEAT );

    //Generate the texture
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, 
GL_RGB, GL_UNSIGNED_BYTE, data);
    free( data ); //free the texture
    return texture; //return whether it was successfull
}

void FreeTexture( GLuint texture )
{
  glDeleteTextures( 1, &texture ); 
}

void drawTiles (void) { //our function to draw the tiles
    for (int i = 0; i < 10; i++) //loop through the height of the map
    {
        for (int j = 0; j < 10; j++) //loop through the width of the map
        {
            if (cMap[i][j] == 0) //if the map at this position contains a 0
            {
                glBindTexture( GL_TEXTURE_2D, texture ); //bind our grass texture to our shape
            }
            else //otherwise
            {
                glBindTexture( GL_TEXTURE_2D, texture2 ); //bind our dirt texture to our shape
            }

            glPushMatrix(); //push the matrix so that our translations only affect this tile
                glTranslatef(j, -i, 0); //translate the tile to where it should belong

                glBegin (GL_QUADS); //begin drawing our quads
                    glTexCoord2d(0.0, 0.0);
                    glVertex3f(0.0, 0.0, 0.0); //with our vertices we have to assign a texcoord

                    glTexCoord2d(1.0, 0.0);
                    glVertex3f(1.0, 0.0, 0.0); //so that our texture has some points to draw to

                    glTexCoord2d(1.0, 1.0);
                    glVertex3f(1.0, 1.0, 0.0);

                    glTexCoord2d(0.0, 1.0);
                    glVertex3f(0.0, 1.0, 0.0);
                glEnd();
            glPopMatrix(); //pop the matrix
        } //end first loop
    } //end second loop
}

void draw() {    
    // clear (has to be done at the beginning)    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    
    glLoadIdentity();     // ToDo: draw our scene 

    // draw ball
    drawRect(ball_pos_x - ball_width / 2, ball_pos_y - ball_height / 2, ball_width, ball_height);



    glEnable( GL_TEXTURE_2D );
    glTranslatef(-5, 4, -20); //translate back a bit to view the map correctly

    drawTiles(); //draw our tiles

    // swap buffers (has to be done at the end)    
    glutSwapBuffers(); 
}




void UpdatePlayer(){
    // hit by right racket?    
    if (ball_pos_x < ball_pos_x + ball_width &&         
        ball_pos_x > enemy_pos_x &&        
        ball_pos_y < enemy_pos_y + enemy_height &&        
        ball_pos_y > enemy_pos_y) {        


            ball_pos_x = ball_pos_x;        
            ball_pos_y = ball_pos_y;    
    }   


}

void update(int value) {   // Call update() again in 'interval' milliseconds   

    // input handling   
    keyboard();  

    UpdatePlayer();

    glutTimerFunc(interval, update, 0);    
    // Redisplay frame   
    glutPostRedisplay(); 
}


void enable2D(int width, int height) {    
    glViewport(0, 0, width, height);    
    glMatrixMode(GL_PROJECTION);    
    glLoadIdentity();    
    glOrtho(0.0f, width, 0.0f, height, 0.0f, 1.0f);    
    glMatrixMode (GL_MODELVIEW);    
    glLoadIdentity(); 
}

void reshape (int w, int h) {
    glViewport (0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode (GL_PROJECTION);
    glLoadIdentity ();
    gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
    glMatrixMode (GL_MODELVIEW);
}

int _tmain(int argc, char** argv)
{

    // initialize opengl (via glut)    
    glutInit(&argc, argv);    
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);    
    glutInitWindowSize(width, height);    glutCreateWindow("noobtuts.com Pong");     

    // Register callback functions       
    glutDisplayFunc(draw);
    glutIdleFunc (draw);
    glutReshapeFunc (reshape);
    glutTimerFunc(interval, update, 0);

    // setup scene to 2d mode and set draw color to white    
    enable2D(width, height);    
    glColor3f(1.0f, 1.0f, 1.0f); 


    //Load our texture
    texture = LoadTexture("texture.raw", 256, 256);
    texture2 = LoadTexture("texture2.raw", 256, 256);

    glutMainLoop ();

    //Free our texture
    FreeTexture(texture);
    FreeTexture(texture2);

    return 0;
}

如果我要在主要评论中发表评论......

glutIdleFunc (draw);
glutReshapeFunc (reshape);

瓷砖地图将消失,我的可移动方块可见并且有效...我只是无法成功实现这两者。我再次对这个全新了,如果我做一些非常愚蠢的事情,我会道歉任何想法,我错了吗?

1 个答案:

答案 0 :(得分:0)

您确定要使用透视投影绘制平铺贴图吗?在我看来,你应该对瓷砖地图和球使用正交投影。

reshape功能更改为只需拨打enable2D(w, h)即可。然后将您的drawTiles功能更改为使用屏幕坐标进行绘制。这应该有用。

一些补充说明:

  • 不要忘记在绘制球时禁用纹理(您似乎没有为它设置任何纹理,因此它只会使用最后一个纹理集进行渲染)。
  • 您也可以使用glDisable(GL_DEPTH_TEST)停用深度测试,因为您并不真正需要它(并使用glVertex2f来绘制平铺图而不是glVertex3f