自由三维视角参考了http://t.csdnimg.cn/5hzu7
贴图资源在最上面,他也可以点击链接https://share.weiyun.com/GOcnS9dh下载,请解压至项目目录,源码放最下面了。
以下是针对其进行的开发:
目录
1搭建了天空盒
2墙壁物理碰撞
3透明图片
4创建怪物(Monster)类
5射击检测
成果在这
1搭建天空盒.
最早采用了三个数组,储存点的x,y,x坐标,再用一个面数组去调用点,不过实际操作挺麻烦的,后面采用结构体形式。
#define SNUM 5
#define PNUM 8
void LoadGLTextures()
{
int i;
const char* pictures[PICNUM] = {
"test\\front.bmp",
"test\\ground.bmp" ,
"test\\top.bmp",
"test\\gd.bmp" ,
"test\\right.bmp",
"test\\right.bmp" ,
"test\\back.bmp",
"test\\coverage.bmp" ,
"test\\zombie.bmp",
"test\\zombiecover.bmp" ,
"test\\zombiep2.bmp" ,
"test\\zombiep2cover.bmp" ,
"test\\zombie0\\down.bmp",
"test\\zombie0\\downcover.bmp",
"test\\zombie0\\leftdown.bmp",
"test\\zombie0\\leftdowncover.bmp",
"test\\gun.bmp",
"test\\guncover.bmp",
"test\\ggg.bmp",
"test\\gggcover.bmp",
"test\\shot.bmp",
"test\\shotcover.bmp",
"test\\title.bmp"
};
先宏定义点(PNUM)和面(SNUM)数量。并且把贴图加载进来
一共8个点(立方体8顶点),5个面(上下左右后,前面我没留,方便)。
点(point)我决定写个结构体
struct point
{
float x;
float y;
float z;
};
下面我将天空盒的搭建封装在room函数中,想创建房子就调用下此函数
void room1(float x1, float z1, float x2, float z2)//四个参数为绘制房间的左下角与右上角坐标,注意此处水平面是xoz面,所以参数是x和z
{
point points[PNUM] = { {x1,0,z1}, {x1,8,z1} ,{x2,8,z1} ,{x2,0,z1}, {x1,0,z2}, {x1,8,z2} , {x2,8,z2} ,{x2,0,z2} };//八个顶点坐标
int surface[SNUM][4] = { {0,1,2,3},{0,1,5,4},{5,1,2,6},{0,3,7,4},{7,6,2,3} };//面调用点的序列{0,1,2,3}代表依次调用0,1,2,3四个顶点来绘制面。
for (int k = 0; k < SNUM; k++)//绘制SUM数量的面
{
glColor3f(1.0, 1.0, 1.0);//先绘制白色四边形
glBegin(GL_QUADS);
for (int i = 0; i < 4; i++)//绘制四个点
{
glVertex3f(points[surface[k][i]].x, points[surface[k][i]].y, points[surface[k][i]].z);//用surface[k][i],k代表第几个面,i代表该面第几个点,从而调用点points
}
glEnd();
glEnable(GL_TEXTURE_2D);//贴图
glBindTexture(GL_TEXTURE_2D, texture[k]);
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex3f(points[surface[k][0]].x, points[surface[k][0]].y, points[surface[k][0]].z);
glTexCoord2f(0, 1); glVertex3f(points[surface[k][1]].x, points[surface[k][1]].y, points[surface[k][1]].z);
glTexCoord2f(1, 1); glVertex3f(points[surface[k][2]].x, points[surface[k][2]].y, points[surface[k][2]].z);
glTexCoord2f(1, 0); glVertex3f(points[surface[k][3]].x, points[surface[k][3]].y, points[surface[k][3]].z);
glEnd();
glDisable(GL_TEXTURE_2D);
}
}
create函数用来完成所有背景创造(考虑到后面可能有多个房间都要绘制)
void createbk()
{
room2(-WIDTH, -16, WIDTH, -48);
room1(-WIDTH, 16, WIDTH, -16);
}
此处写了两个不同的房间room1和room2,调用参数为房间地板坐下与右上角,WIDTH是我定义的宽度暂定为4.0。
最后在display里调用createbk函数
void display(void)
{
// 清除屏幕
if (shot > 0)
{
shot--;
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除屏幕及深度缓存
// 深度测试开启,实现遮挡关系
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
// 设置视角
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, 1, 0.1, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(cpos_x, cpos_y, cpos_z, cpos_x + look_x, cpos_y + look_y, cpos_z - look_z, 0, 1, 0);//注意因为相机是面朝z负方向,所以cpos_z - lookz
//gluLookAt(cpos_x, cpos_y, cpos_z, 0, 0, 0, 0, 1, 0);//原固定视角
if(flag)
start();
judge();
createbk();
if (!flag)
{
sort();
gun();
}
glutSwapBuffers();
}
先写到这,别的后面再更新,源码如下。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cmath>
#include<windows.h>
#include<stdlib.h>
#include<math.h>
#include<gl/glaux.h>
#include <tchar.h>
#define _CRT_SECURE_NO_WARNINGS
#define WindowWidth 1200
#define WindowHeight 600
#define WindowTitle "第一人称视角漫游demo"
#define SNUM 5
#define PNUM 8
#define WIDTH 4
#define PICNUM 50
#define MW 0.8
#define MH 5
#define MNUM 5
#include <gl\glut.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include<iostream>
using namespace std;
#pragma comment(lib, "glaux")
float rot = 0;
GLuint texture[PICNUM];
void LoadGLTextures();
void picture(int i);
bool lose = false;
float PI = 3.14;
//视角控制
float look_x = 0,
look_y = 0,
look_z = 0,
look_x_temp = 0,
look_z_temp = 0;
float screenrate_x, screenrate_y;//鼠标屏幕坐标相对于中心点移动的比例
float r = 10;
//相机位置
float cpos_x = 0,
cpos_y = 3,
cpos_z = 10;
const float step = 0.01;
int centerpoint_x = WindowWidth / 2,
centerpoint_y = WindowHeight / 2;
int shot = 0;
int myscore = 0;
int shottime = 0;
void transp(int i1, int i2, float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, float x4, float y4, float z4);
void timefunction(int value);
int ord = 0;
struct point
{
float x;
float y;
float z;
};
void room1(float x1, float z1, float x2, float z2)//四个参数为绘制房间的左下角与右上角坐标,注意此处水平面是xoz面,所以参数是x和z
{
point points[PNUM] = { {x1,0,z1}, {x1,8,z1} ,{x2,8,z1} ,{x2,0,z1}, {x1,0,z2}, {x1,8,z2} , {x2,8,z2} ,{x2,0,z2} };//八个顶点坐标
int surface[SNUM][4] = { {0,1,2,3},{0,1,5,4},{5,1,2,6},{0,3,7,4},{7,6,2,3} };//面调用点的序列{0,1,2,3}代表依次调用0,1,2,3四个顶点来绘制面。
for (int k = 0; k < SNUM; k++)//绘制SUM数量的面
{
glColor3f(1.0, 1.0, 1.0);//先绘制白色四边形
glBegin(GL_QUADS);
for (int i = 0; i < 4; i++)//绘制四个点
{
glVertex3f(points[surface[k][i]].x, points[surface[k][i]].y, points[surface[k][i]].z);//用surface[k][i],k代表第几个面,i代表该面第几个点,从而调用点points
}
glEnd();
glEnable(GL_TEXTURE_2D);//贴图
glBindTexture(GL_TEXTURE_2D, texture[k+ord]);
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex3f(points[surface[k][0]].x, points[surface[k][0]].y, points[surface[k][0]].z);
glTexCoord2f(0, 1); glVertex3f(points[surface[k][1]].x, points[surface[k][1]].y, points[surface[k][1]].z);
glTexCoord2f(1, 1); glVertex3f(points[surface[k][2]].x, points[surface[k][2]].y, points[surface[k][2]].z);
glTexCoord2f(1, 0); glVertex3f(points[surface[k][3]].x, points[surface[k][3]].y, points[surface[k][3]].z);
glEnd();
glDisable(GL_TEXTURE_2D);
}
}
bool flag = true;
void start()
{
float t1 = sqrt(look_x * look_x + look_z * look_z);
float y = cpos_y + look_y / 20;
float x0 = cpos_x + (look_x_temp / 20) * cos(-screenrate_y + 0.2 * PI) ;
float z0 = cpos_z - (look_z_temp / 20) * cos(-screenrate_y + 0.2 * PI) ;
float x00 = cpos_x + (look_x_temp / 20) * cos(-screenrate_y - 0.2 * PI);
float z00 = cpos_z - (look_z_temp / 20) * cos(-screenrate_y - 0.2 * PI);
float x1 = x0 + 0.25 * (look_z) / t1;
float z1 = z0 + 0.25 * (look_x) / t1;
float x2 = x0 - 0.25 * (look_z) / t1 ;
float z2 = z0 - 0.25 * (look_x) / t1;
float x3 = x00 + 0.25 * (look_z) / t1;
float z3 = z00 + 0.25 * (look_x) / t1;
float x4 = x00 - 0.25 * (look_z) / t1;
float z4 = z00 - 0.25 * (look_x) / t1;
int d = 15;
float yd = cpos_y+r * sin(-screenrate_y+0.2*PI)/20;
float yd2 = cpos_y + r * sin(-screenrate_y - 0.2 * PI)/20;
transp(27, 22, x3 , yd2, z3 ,
x1 , yd , z1 ,
x2 , yd , z2 ,
x4 , yd2 , z4);
printf("%f,%f,%f\n", cpos_x + look_x / 10 + look_z_temp / 10, cpos_y + look_y, cpos_z - look_z / 10 + look_x_temp / 10);
}
class monster
{
private:
float x;
float y;
float health;
float angle;
float angle2;
float time;
float direction;
int death;
float dx;
float dy;
float angle1;
int pic2;
int cover2;
int pic;
int cover;
int willdie;
int count;
int diep;
int diec;
public:
void changeskin(int p1,int p2,int p3,int p4,int p5,int p6)
{
pic = p1;
cover = p2;
pic2 = p3;
cover2 = p4;
diep = p5;
diec = p6;
}
monster(float setx, float sety, int h)
{
x = setx;
y = sety;
health = h;
time = 0;
direction = 1;
death = 0;
pic = 8;
willdie = 0;
cover = 9;
count = 0;
pic2 = 12;
cover2 = 13;
diep = 23;
diec = 24;
}
void walk()
{
dx = (cpos_x - x) / sqrt((cpos_x - x) * (cpos_x - x) + (cpos_z - y) * (cpos_z - y));
dy = (cpos_z - y) / sqrt((cpos_x - x) * (cpos_x - x) + (cpos_z - y) * (cpos_z - y));
if (!death)
{
x += dx * step;
y += dy * step;
draw();
time += direction / 2;
if (time == 20)direction = -1;
if (time == -20)direction = 1;
}
}
float getlength()
{
return sqrt((cpos_x - x) * (cpos_x - x) + (cpos_z - y) * (cpos_z - y));
}
void body(float x1, float y1, float x2, float y2, float speed1, float speed2)
{
glEnable(GL_BLEND);
glBlendFunc(GL_DST_COLOR, GL_ZERO);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture[cover2]);
glBegin(GL_QUADS);
glTexCoord2f(x1, y1); glVertex3f(x + 2 * MW * angle2 * (x1 - 0.5) + time / 20 * dx * speed1, MH * y1, y - 2 * MW * angle * (x1 - 0.5) + time / 20 * dy * speed1);
glTexCoord2f(x1, y2); glVertex3f(x + 2 * MW * angle2 * (x1 - 0.5) + time / 20 * dx * speed2, MH * y2, y - 2 * MW * angle * (x1 - 0.5) + time / 20 * dy * speed2);
glTexCoord2f(x2, y2); glVertex3f(x + 2 * MW * angle2 * (x2 - 0.5) + time / 20 * dx * speed2, MH * y2, y - 2 * MW * angle * (x2 - 0.5) + time / 20 * dy * speed2);
glTexCoord2f(x2, y1); glVertex3f(x + 2 * MW * angle2 * (x2 - 0.5) + time / 20 * dx * speed1, MH * y1, y - 2 * MW * angle * (x2 - 0.5) + time / 20 * dy * speed1);
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[pic2]);
glBlendFunc(GL_ONE, GL_ONE);
glBegin(GL_QUADS);
glTexCoord2f(x1, y1); glVertex3f(x + 2 * MW * angle2 * (x1 - 0.5) + time / 20 * dx * speed1, MH * y1, y - 2 * MW * angle * (x1 - 0.5) + time / 20 * dy * speed1);
glTexCoord2f(x1, y2); glVertex3f(x + 2 * MW * angle2 * (x1 - 0.5) + time / 20 * dx * speed2, MH * y2, y - 2 * MW * angle * (x1 - 0.5) + time / 20 * dy * speed2);
glTexCoord2f(x2, y2); glVertex3f(x + 2 * MW * angle2 * (x2 - 0.5) + time / 20 * dx * speed2, MH * y2, y - 2 * MW * angle * (x2 - 0.5) + time / 20 * dy * speed2);
glTexCoord2f(x2, y1); glVertex3f(x + 2 * MW * angle2 * (x2 - 0.5) + time / 20 * dx * speed1, MH * y1, y - 2 * MW * angle * (x2 - 0.5) + time / 20 * dy * speed1);
glEnd();
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
}
void draw()
{
if (willdie)
{
count++;
}
if (count >= 40)
{
health = 0;
death = 1;
myscore += 5;
}
glColor3f(1, 1, 1);
glBegin(GL_QUADS);
glVertex3f(x - MW * angle2 * health / 5, MH, y + MW * angle * health / 5);
glVertex3f(x - MW * angle2 * health / 5, MH + 0.2, y + MW * angle * health / 5);
glVertex3f(x + MW * angle2 * health / 5, MH + 0.2, y - MW * angle * health / 5);
glVertex3f(x + MW * angle2 * health / 5, MH, y - MW * angle * health / 5);
glEnd();
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture[25]);
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex3f(x - MW * angle2 * health / 5, MH, y + MW * angle * health / 5);
glTexCoord2f(0, 1); glVertex3f(x - MW * angle2 * health / 5, MH + 0.2, y + MW * angle * health / 5);
glTexCoord2f(1, 1); glVertex3f(x + MW * angle2 * health / 5, MH + 0.2, y - MW * angle * health / 5);
glTexCoord2f(1, 0); glVertex3f(x + MW * angle2 * health / 5, MH, y - MW * angle * health / 5);
glEnd();
glDisable(GL_TEXTURE_2D);
const float cut = 0.36;
const float cut3 = 0.2;
const float cut2 = 0.48;
angle = (cpos_x - x) / sqrt((cpos_x - x) * (cpos_x - x) + (cpos_z - y) * (cpos_z - y));
angle2 = (cpos_z - y) / sqrt((cpos_x - x) * (cpos_x - x) + (cpos_z - y) * (cpos_z - y));
glEnable(GL_BLEND);
glBlendFunc(GL_DST_COLOR, GL_ZERO);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture[cover]);
glBegin(GL_QUADS);
glTexCoord2f(0, cut2); glVertex3f(x - MW * angle2, MH * cut2, y + MW * angle);
glTexCoord2f(0, 1); glVertex3f(x - MW * angle2, MH, y + MW * angle);
glTexCoord2f(1, 1); glVertex3f(x + MW * angle2, MH, y - MW * angle);
glTexCoord2f(1, cut2); glVertex3f(x + MW * angle2, MH * cut2, y - MW * angle);
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[pic]);
glBlendFunc(GL_ONE, GL_ONE);
glBegin(GL_QUADS);
glTexCoord2f(0, cut2); glVertex3f(x - MW * angle2, MH * cut2, y + MW * angle);
glTexCoord2f(0, 1); glVertex3f(x - MW * angle2, MH, y + MW * angle);
glTexCoord2f(1, 1); glVertex3f(x + MW * angle2, MH, y - MW * angle);
glTexCoord2f(1, cut2); glVertex3f(x + MW * angle2, MH * cut2, y - MW * angle);
glEnd();
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
body(0, 0.1, 0.5, 0.3, 1, 1);
body(0, 0.3, 0.5, 0.48, 1, 0);
body(0.5, 0.1, 1, 0.3, -1.2, -1);
body(0.5, 0.3, 1, 0.48, -1, 0);
}
bool create()
{
if (death == 1)
{
death = 0;
willdie = 0;
count = 0;
health = 5;
x = 0, y = -30;
pic = 8;
cover = 9;
diep = 23;
diec = 24;
pic2 = 12;
cover2 = 13;
return true;
}
else return false;
}
bool die()
{
float len = getlength();
float r = ((x - cpos_x) / (look_x)) / ((y - cpos_z) / (-look_z));
float ry = ((MH - cpos_y) / len) / (look_y / 10);
printf("%f\n", ry);
if (death == 1)return false;
else if ((r) > 1 - 3 / len && (r) < 1 + 3 / len)
{
printf("\n%f", ry);
if (ry > 1.4 && ry < 1.9)
{
pic = diep;
cover = diec;
willdie = 1;
}
health -= 10 / getlength();
if (health <= 0)
{
death = 1;
myscore++;
}
return true;
}
return false;
}
bool willlose()
{
if (getlength() <= 1 && !death)
{
float t1 = sqrt(look_x * look_x + look_z * look_z);
float y = cpos_y + look_y / 20;
float x = cpos_x + (look_x / 20);
float z = cpos_z - (look_z / 20);
float x1 = x + 0.3 * (look_z) / t1;
float z1 = z + 0.3 * (look_x) / t1;
float x2 = x - 0.3 * (look_z) / t1;
float z2 = z - 0.3 * (look_x) / t1;
lose = true;
transp(27, 26, x2 + (look_y / 15) * (look_x) / t1, y - 0.35, z2 - (look_y / 15) * (look_z) / t1, x2 - (look_y / 15) * (look_x) / t1, y + 0.35, z2 + (look_y / 15) * (look_z) / t1, x1 - (look_y / 15) * (look_x) / t1, y + 0.35, z1 + (look_y / 15) * (look_z) / t1, x1 + (look_y / 15) * (look_x) / t1, y - 0.35, z1 - (look_y / 15) * (look_z) / t1);
printf("%f,%f,%f\n", cpos_x + look_x / 10 + look_z_temp / 10, cpos_y + look_y, cpos_z - look_z / 10 + look_x_temp / 10);
printf("%f,%f,%f", cpos_x, cpos_y, cpos_z);
glFlush();
return true;
}
return false;
}
};
void transp(int i1, int i2, float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, float x4, float y4, float z4)
{
glEnable(GL_BLEND);
glBlendFunc(GL_DST_COLOR, GL_ZERO);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture[i1]);
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex3f(x1, y1, z1);
glTexCoord2f(0, 1); glVertex3f(x2, y2, z2);
glTexCoord2f(1, 1); glVertex3f(x3, y3, z3);
glTexCoord2f(1, 0); glVertex3f(x4, y4, z4);
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[i2]);
glBlendFunc(GL_ONE, GL_ONE);
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex3f(x1, y1, z1);
glTexCoord2f(0, 1); glVertex3f(x2, y2, z2);
glTexCoord2f(1, 1); glVertex3f(x3, y3, z3);
glTexCoord2f(1, 0); glVertex3f(x4, y4, z4);
glEnd();
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
}
monster m1(1, -10, 5);
monster m2(-1, -15, 5);
monster m3(-2, -20, 5);
monster m4(0, -25, 5);
monster m5(3, -30, 5);
monster m[MNUM] = { m1,m2,m3,m4,m5 };
int order[MNUM];
void recreate()
{
for (int i = 0; i < MNUM; i++)
{
if (m[i].create())
break;
}
}
void sort()
{
for (int i = 0; i < MNUM; i++)
{
order[i] = i;
}
int temp = 0;
for (int i = 0; i < MNUM; i++)
{
for (int j = MNUM - i - 1; j >= i; j--)
{
if (m[order[i]].getlength() < m[order[j]].getlength())
{
temp = order[i];
order[i] = order[j];
order[j] = temp;
}
}
}
for (int i = 0; i < MNUM; i++)
{
m[order[i]].walk();
}
}
void gun()
{
float t = sqrt(look_x * look_x + look_z * look_z + look_y * look_y);
glLineWidth(5);
glBegin(GL_LINES);
glVertex3f(cpos_x + look_x / t, cpos_y + look_y / t + 0.03, cpos_z - look_z / t);
glVertex3f(cpos_x + look_x / t, cpos_y + look_y / t + 0.01, cpos_z - look_z / t);
glVertex3f(cpos_x + look_x / t, cpos_y + look_y / t - 0.03, cpos_z - look_z / t);
glVertex3f(cpos_x + look_x / t, cpos_y + look_y / t - 0.01, cpos_z - look_z / t);
glVertex3f(cpos_x + look_x / t + 0.01 * look_z / t, cpos_y + look_y / t, cpos_z - look_z / t + 0.01 * look_x / t);
glVertex3f(cpos_x + look_x / t + 0.03 * look_z / t, cpos_y + look_y / t, cpos_z - look_z / t + 0.03 * look_x / t);
glVertex3f(cpos_x + look_x / t - 0.01 * look_z / t, cpos_y + look_y / t, cpos_z - look_z / t - 0.01 * look_x / t);
glVertex3f(cpos_x + look_x / t - 0.03 * look_z / t, cpos_y + look_y / t, cpos_z - look_z / t - 0.03 * look_x / t);
glEnd();
float t1 = sqrt(look_x * look_x + look_z * look_z);
float y = cpos_y + look_y / 15;
float x = cpos_x + (look_x / 15);
float z = cpos_z - (look_z / 15);
float x1 = x + (look_z / 4) / t1;
float z1 = z + (look_x / 4) / t1;
if (shot == 0)
{
transp(19, 18, x1 + (look_y / 15) * (look_x) / t1, y - 0.5, z1 - (look_y / 15) * (look_z) / t1, x1, y, z1, x, y, z, x + (look_y / 15) * (look_x) / t1, y - 0.5, z - (look_y / 15) * (look_z) / t1);
}
else
{
transp(21, 20, x1 + (look_y / 15) * (look_x) / t1, y - 0.5, z1 - (look_y / 15) * (look_z) / t1, x1, y, z1, x, y, z, x + (look_y / 15) * (look_x) / t1, y - 0.5, z - (look_y / 15) * (look_z) / t1);
}
//printf("%f,%f,%f,%f,%f,%f,%f,%f,%f\n", x1 + (look_y / 15) * (look_x / 20), y - 0.5, z1 - (look_y / 15) * (look_z / 20), x1, y, z1, x, y, z, x + (look_y / 15) * (look_x / 20), y - 0.5, z - (look_y / 15) * (look_z / 20));
}
void score()
{
int a = clock();
const char* str = "Score:";
char score[16] = { 0 };
_itoa(myscore, score, 10);
int n = strlen(str);
glRasterPos3f(cpos_x + look_x / 10 - look_z_temp / 20, cpos_y + look_y / 10, cpos_z - look_z / 10 - look_x_temp / 20);
for (int i = 0; i < n; i++)
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, *(str + i));
for (int i = 0; i < 16; i++)
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, score[i]);
glFlush();
}
void LoadGLTextures()
{
int i;
const char* pictures[PICNUM] = {
"test\\front.bmp",
"test\\ground.bmp" ,
"test\\top.bmp",
"test\\gd.bmp" ,
"test\\right.bmp",
"test\\right.bmp" ,
"test\\back.bmp",
"test\\coverage.bmp" ,
"test\\zombie.bmp",
"test\\zombiecover.bmp" ,
"test\\zombiep2.bmp" ,
"test\\zombiep2cover.bmp" ,
"test\\zombie0\\down.bmp",
"test\\zombie0\\downcover.bmp",
"test\\zombie0\\leftdown.bmp",
"test\\zombie0\\leftdowncover.bmp",
"test\\gun.bmp",
"test\\guncover.bmp",
"test\\ggg.bmp",
"test\\gggcover.bmp",
"test\\shot.bmp",
"test\\shotcover.bmp",
"test\\title.bmp",
"test\\dead.bmp",
"test\\deadcover.bmp",
"test\\blood.bmp",
"test\\lose.bmp",
"test\\losecover.bmp",
"test\\body\\warrior.bmp",
"test\\body\\warriorcover.bmp",
"test\\body\\wd.bmp",
"test\\body\\wdc.bmp",
"test\\body\\fox.bmp",
"test\\body\\foxc.bmp",
"test\\body\\fu.bmp",
"test\\body\\fuc.bmp",
"test\\body\\ph.bmp",
"test\\body\\phc.bmp",
"test\\body\\ac.bmp",
"test\\body\\acc.bmp",
"test\\bk1\\f.bmp",
"test\\bk1\\l.bmp",
"test\\bk1\\u.bmp",
"test\\bk1\\l.bmp",
"test\\bk1\\r.bmp",
"test\\bk2\\f.bmp",
"test\\bk2\\l.bmp",
"test\\bk2\\u.bmp",
"test\\bk2\\l.bmp",
"test\\bk2\\r.bmp"
};
AUX_RGBImageRec* TextureImage[PICNUM];
::memset(TextureImage, 0, sizeof(void*) * PICNUM);
for (i = 0; i < PICNUM; i++)
{
TextureImage[i] = auxDIBImageLoad(pictures[i]);
if (TextureImage[i]) //纹理是否存在
{
glGenTextures(1, &texture[i]); //创建纹理
glBindTexture(GL_TEXTURE_2D, texture[i]); //绑定纹理
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[i]->sizeX, TextureImage[i]->sizeY, 0,
GL_RGB, GL_UNSIGNED_BYTE, TextureImage[i]->data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
free(TextureImage[i]); //释放图像结构变量占用的内存
}
}
}
void createbk()
{
room1(-WIDTH, -48, WIDTH, -16);
room1(-WIDTH, 16, WIDTH, -16);
}
//不按鼠标移动事件
void onMouseMovePassive(int screen_x, int screen_y)
{
float offsetx = screen_x - centerpoint_x;
float offsety = screen_y - centerpoint_y;
screenrate_x = offsetx / centerpoint_x * 1.5 * PI;//用于摄像机水平移动
screenrate_y = offsety / centerpoint_y * 0.8 * PI;//用于摄像机上下移动
//水平方向
look_x_temp = r * sin(screenrate_x);
look_z_temp = r * cos(screenrate_x);
//最后使用时要和相机坐标相加/减
//竖直方向
look_y = r * sin(-screenrate_y);
float r_castlenght = abs(r * cos(screenrate_y));
//投影在xz面的长度
//根据长度计算真正的look_x,look_z
look_x = r_castlenght * look_x_temp / r;
look_z = r_castlenght * look_z_temp / r;
}
//按下鼠标移动事件
void onMouseDownAndMove(int x, int y) {
}
void judge()
{
if (shottime > 0)
{
shottime--;
}
if (cpos_x < -WIDTH)
{
cpos_x += step * 11;
}
if (cpos_x > WIDTH)
{
cpos_x -= step * 11;
}if (cpos_z < -48)
{
cpos_z += step * 11;
}if (cpos_z > 16)
{
cpos_z -= step * 11;
}
}
void los()
{
for (int i = 0; i < MNUM; i++)
{
m[i].willlose();
}
}
void OnMouse(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
if (shottime == 0)
for (int i = MNUM-1; i >=0; i--)
{
shot = 5;
if (m[order[i]].die())break;
}
flag = false;
if (shottime == 0)
shottime = 30;
}
}
void restart();
void restart()
{
monster m1(1, -10, 5);
monster m2(-1, -15, 5);
monster m3(-2, -20, 5);
monster m4(0, -25, 5);
monster m5(3, -30, 5);
m[0] = m1;
m[1] = m2;
m[2] = m3;
m[3] = m4;
m[4] = m5;
cpos_x = 0;
cpos_y = 3;
cpos_z = 10;
lose = false;
glutTimerFunc(1, timefunction, 1);
}
void InitLight() {
GLfloat light_position0[] = { 0,2,0,1 };
GLfloat light_ambient0[] = { 1,1,1,1 }; //环境光,控制物体颜色
GLfloat light_diffuse0[] = { 1,1,1,1 };//可改变漫反射光颜色(默认值为(1,1,1,1))
GLfloat light_specular0[] = { 1,1,1,1 }; //镜面反射RGBA强度值(默认值为(1,1,1,1))
GLfloat light_position1[] = { 1,2,-10,1 };
GLfloat light_ambient1[] = { 1,1,1,1 }; //环境光,控制物体颜色
GLfloat light_diffuse1[] = { 1,1,1,1 }; //漫反射
GLfloat light_specular1[] = { 1,1,1,1 };
GLfloat light_position2[] = { 10,2,0,1 };
GLfloat light_ambient2[] = { 1,1,1,1 }; //环境光,控制物体颜色
GLfloat light_diffuse2[] = { 1,1,1,1 };//可改变漫反射光颜色(默认值为(1,1,1,1))
GLfloat light_specular2[] = { 1,1,1,1 }; //镜面反射RGBA强度值(默认值为(1,1,1,1))
glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient0);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse0);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular0);
glLightfv(GL_LIGHT1, GL_POSITION, light_position1);
glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient1);
glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse1);
glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular1);//光源号GL_LIGHT0
glLightfv(GL_LIGHT2, GL_POSITION, light_position2);
glLightfv(GL_LIGHT2, GL_AMBIENT, light_ambient2);
glLightfv(GL_LIGHT2, GL_DIFFUSE, light_diffuse2);
glLightfv(GL_LIGHT2, GL_SPECULAR, light_specular2);//光源号GL_LIGHT0
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_LIGHT2);
}
void display(void)
{
// 清除屏幕
if (shot > 0)
{
shot--;
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除屏幕及深度缓存
// 深度测试开启,实现遮挡关系
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glShadeModel(GL_SMOOTH);
// 设置视角
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, 1, 0.1, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(cpos_x, cpos_y, cpos_z, cpos_x + look_x, cpos_y + look_y, cpos_z - look_z, 0, 1, 0);//注意因为相机是面朝z负方向,所以cpos_z - lookz
//gluLookAt(cpos_x, cpos_y, cpos_z, 0, 0, 0, 0, 1, 0);//原固定视角
if (flag)
start();
judge();
createbk();
if (!flag)
{
sort();
gun();
}
score();
los();
glutSwapBuffers();
}
void display2()
{
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
glViewport(0, 0, 800, 1600);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, (double)800, 0, (double)1600);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1, 0, 0);
glBegin(GL_POLYGON);
glVertex2f(0, 0);
glVertex2f(0, 1);
glVertex2f(1, 1);
glVertex2f(1, 0);
glEnd();
glFlush();
glutSwapBuffers();
Sleep(100000);
}
void keyboardFunc(unsigned char key, int x, int y)
{
if (key == 'w') {
//朝镜头方向前进look_x,look_z
cpos_x += look_x_temp * step;
cpos_z -= look_z_temp * step;
}
if (key == 's') {
cpos_x -= look_x_temp * step;
cpos_z += look_z_temp * step;
}
if (key == 'a') {
//左 (x,y)对应(y,-x)
//则(look_x,look_z)对应的为(-look_z,look_x)
//Z轴取反
cpos_x += -look_z_temp * step;
cpos_z -= look_x_temp * step;
}
if (key == 'd') {
//右 (x,y)对应(-y,x)
//则(look_x,look_z)对应的为(look_z,-look_x)
//Z轴取反
cpos_x += look_z_temp * step;
cpos_z -= -look_x_temp * step;
}
if (key == 'q')
{
recreate();
}
if (key == 'r')
{
if(lose)
restart();
}
if (key == '1')
{
for (int i = 0; i < MNUM; i++)
{
m[i].changeskin(28, 29, 28, 29,30,31);
}
}
if (key == '2')
{
for (int i = 0; i < MNUM; i++)
{
m[i].changeskin(32, 33, 32, 33, 32, 33);
}
}if (key == '3')
{
for (int i = 0; i < MNUM; i++)
{
m[i].changeskin(34, 35, 34, 35, 34, 35);
}
}if (key == '4')
{
for (int i = 0; i < MNUM; i++)
{
m[i].changeskin(36, 37, 36, 37, 36, 37);
}
}if (key == '5')
{
for (int i = 0; i < MNUM; i++)
{
m[i].changeskin(38, 39, 38, 39, 38, 39);
}
}
if (key == '6')
{
ord = 40;
}
if (key == '7')
{
ord = 45;
}
if (key == '8')
{
ord = 0;
}
}
void timefunction(int value)
{
if (!lose)
display();
if (!lose)
glutTimerFunc(1, timefunction, 1);
if(lose)
glutKeyboardFunc(keyboardFunc);
}
int main(int argc, char* argv[])
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowPosition(100, 100);
glutInitWindowSize(WindowWidth, WindowHeight);
glutCreateWindow(WindowTitle);
glutPassiveMotionFunc(onMouseMovePassive);
glutMotionFunc(onMouseDownAndMove);
glutKeyboardFunc(keyboardFunc);
LoadGLTextures();
//InitLight();
//glEnable(GL_CULL_FACE);
//glEnable(GL_DEPTH_TEST);
glutDisplayFunc(&display);
glutTimerFunc(1, timefunction, 1);
glutMouseFunc(&OnMouse);
glutMainLoop();
return 0;
}