nenuzhno-engine_iter1/demos/tpsGame/init.cpp

484 lines
10 KiB
C++

#include "log.h"
#include "engine.h"
#include "game/IGame.h"
#include "graphics/gl_utils.h"
#include "graphics/texture.h"
#include "renderer/renderer.h"
#include "renderer/Model.h"
#include "renderer/camera.h"
#include "resource/ResourceManager.h"
#include "system/FileSystem.h"
#include "button.h"
#include "system/config.h"
#include "tpsMaterials.h"
#include "tpsPlayer.h"
#include "tpsPhysics.h"
#include "tpsObjects.h"
#include "tpsMenu.h"
using namespace std;
using glm::vec2;
using glm::vec3;
using glm::mat4;
using glm::translate;
using glm::scale;
using glm::dot;
using glm::normalize;
using glm::mix;
using glm::radians;
Scene *LoadTXTScene(const char *fileName,ResourceManager *resMan,PhysicsSystem *physics);
Texture *GenerateStarBox(int size, int count);
std::string strGameLog;
glm::vec3 atovec3(const char *str)
{
glm::vec3 out(0);
sscanf(str, "%f %f %f", &out.x, &out.y, &out.z);
return out;
}
void GameLog(const char *s){
Log("Game: %s",s);
strGameLog+=s;
}
//TODO interacting objects
std::vector<ButtonObject*> g_buttons;
std::vector<Projectile*> g_projs;
enum eGameState{
eGameMenu=1,
eGamePlay=2,
eGamePause=3
};
class tpsGame:public IGame
{
void Created();
void Changed(int w, int h);
void Draw();
const char *GetGamedir(){
return "tpsGame";
}
void OnKey(int key, int scancode, int action, int mods);
void OnTouch(float tx, float ty, int ta, int tf);
void OnMouseMove(float x, float y);
void Update(float dt);
void InitTouch();
void UpdateMouse(float deltaTime);
void StartGame();
void ResumeGame();
void PauseGame();
eGameState gameState;
ResourceManager *resMan;
IRenderer *renderer;
PhysicsSystem *physics;
Scene *scene;
Texture *starBox;
Camera cam;
double oldTime;
Player *player;
Joystick joyM;
Joystick joyL;
KeyJoystick keyM;
vec2 mousePos;
vec2 lastMousePos;
Button bJump;
Button bUse;
Button bAttack;
Button bPause;
StaticModel *box1;
//ButtonObject *button1;
//DoorObject *door1;
ButtonObject *curButt;
LightObject *lamp1;
Weapon pistol;
vec3 pistOffs;
tpsMenu menu;
tpsSettings settings;
float lastScreenScale;
std::string startScene;
friend void tpsStartGame();
friend void tpsResumeGame();
friend void ShootBullet(vec3 orig, vec3 dir);
};
tpsGame *g_game;
IGame *CreateGame()
{
return (g_game=new tpsGame());
}
Model *g_mdlBox=0;
void ShootBullet(vec3 orig, vec3 dir)
{
Projectile *p = new Projectile(orig,dir);
g_projs.push_back(p);
g_game->scene->AddObject(p);
}
void tpsGame::InitTouch()
{
joyM = Joystick(0,0.3,0.5,0.7);
joyL = Joystick(0.5,0,0.5,1);
bJump = Button(0.7,0.5,0.2,0.2);
bUse = Button(0.15,0.25,0.2,0.2);
bAttack = Button(0.75,0.25,0.2,0.2,true);
bPause = Button(0.9,0.1,0.1,0.1);
}
void tpsStartGame()
{
g_game->StartGame();
}
void tpsResumeGame()
{
g_game->ResumeGame();
}
void tpsGame::ResumeGame()
{
gameState = eGamePlay;
//InitTouch();
renderer->SetScene(scene);
EnableCursor(false);
}
void tpsGame::PauseGame()
{
gameState = eGamePause;
renderer->SetScene(0);
EnableCursor(true);
}
void tpsGame::StartGame()
{
gameState = eGamePlay;
Model *mdlBox = resMan->GetModel("cube.nmf");
g_mdlBox = mdlBox;
scene = LoadTXTScene(startScene.c_str(),resMan,physics);
starBox = GenerateStarBox(256,128);
scene->skyBox = starBox;
InitTouch();
Model *mdlChar = resMan->GetModel("char1.nmf");
player = new Player(&cam,scene->startPos,scene->startRot,mdlChar);
#ifdef ANDROID
player->move = &joyM;
#else
keyM = KeyJoystick(IN_KEY_W,IN_KEY_S,IN_KEY_D,IN_KEY_A);
player->move = &keyM;
#endif
player->look = &joyL;
player->jump = &bJump;
player->bAttack = &bAttack;
player->phys = physics->CreatePlayer(1,0.4,player->modelMtx);
scene->AddObject(player);
box1 = new StaticModel();
box1->mdl = mdlBox;
box1->modelMtx = translate(mat4(1.0f),vec3(1.0f,6.0f,-3.0f));
physics->AddBox(vec3(1),box1,100);
scene->AddObject(box1);
/*
door1 = new DoorObject(vec3(-3.5,1,3.5),mdlBox);
scene->AddObject(door1);
button1 = new ButtonObject(vec3(-2,1.5f,3.0f));
button1->mdl = mdlBox;
button1->target = door1;
button1->name = "Button1";
button1->text = "Open door";
scene->AddObject(button1);
*/
//lamp1 = new LightObject(ePoint,vec3(-20.4,1.6,3.5),vec3(0.8,0.8,1),5);
//scene->AddLight(lamp1);
Model *pistolMdl = resMan->GetModel("pistol1.nmf");
pistol = Weapon(eWeapPistol,pistolMdl,5,2);
pistol.offsetMtx = rotate(translate(mat4(1),pistOffs),radians(90.0f),vec3(0,1,0));
player->weapon = &pistol;
curButt = 0;
renderer->SetScene(scene);
EnableCursor(false);
}
void tpsGame::Created()
{
gameState = eGameMenu;
resMan = new ResourceManager();
resMan->Init();
resMan->AddMaterialLoader(new TXTMaterialLoader(resMan));
renderer = CreateRenderer();
renderer->Init(RENDERER_GUI|RENDERER_LIGHT|RENDERER_BACKBUFFER,resMan);
ConfigFile config;
config.Load("tpsConfig.txt");
settings.Load(config);
/*for(uint32_t i=0;i<config.values.size();i++){
map<string,string>::iterator it = config.values.begin()+i;
Log("cfg %d: %s=%s\n",i,it.first->c_str(),it.second->c_str());
}*/
renderer->debug = settings.drawBbox;
lastScreenScale=settings.screenScale;
renderer->SetBackBufferScale(settings.screenScale);
startScene = config.values["startScene"];
pistOffs = atovec3(config.values["pistOffs"].c_str());
physics = new PhysicsSystem();
physics->Init(settings.debugPhysics?renderer:0);
menu.Init(&settings,renderer);
//StartGame();
mousePos = vec2(0);
lastMousePos = vec2(0);
Log("tpsGame Init %f\n",GetTime());
oldTime = GetTime();
}
void tpsGame::Changed(int w, int h)
{
renderer->Resize(w,h);
cam.UpdateProj(80.0f,renderer->aspect,0.05f,100.0f);
renderer->SetCamera(&cam);
menu.Resize(renderer->aspect);
InitTouch();
}
void tpsGame::Update(float deltaTime){
menu.Update(deltaTime);
if(gameState==eGamePlay){
//TODO fixed update
#ifndef ANDROID
float mouseSens=0.2f;
joyL.vel = (mousePos-lastMousePos)/vec2(renderer->width,renderer->height)*mouseSens;
lastMousePos = mousePos;
#endif
if(lastScreenScale!=settings.screenScale){
lastScreenScale=settings.screenScale;
renderer->SetBackBufferScale(settings.screenScale);
}
player->tps = settings.tps;
physics->Update(deltaTime);
scene->Update(deltaTime);
if(bPause.pressed){
bPause.pressed = false;
PauseGame();
}
curButt = 0;
float curButtDist=99;
for(uint32_t i=0; i<g_buttons.size();i++){
g_buttons[i]->rot=player->rot.y;
if(glm::distance(g_buttons[i]->pos,player->cam->pos)>2.0f)
continue;
float buttDist = dot(normalize(g_buttons[i]->pos-player->cam->pos),player->view);
if(buttDist>0.9){
if(buttDist<curButtDist){
curButt = g_buttons[i];
curButtDist = buttDist;
}
}
}
if(bUse.pressed){
bUse.pressed = false;
if(curButt)
curButt->Press(player);
}
}
}
void tpsGame::Draw(){
double startTime = GetTime();
float deltaTime = (startTime-oldTime);
oldTime = startTime;
Update(deltaTime);
renderer->Draw();
if(gameState==eGamePlay){
//if(player->phys->onGround())
// renderer->DrawText("on ground",0.02,0.1,0.4);
if(curButt){
renderer->DrawText(curButt->text.c_str(),0.4*renderer->aspect,0.9,0.5);
}
//touch
if(settings.drawTouch){
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
renderer->SetColor(1,1,1,0.2);
Button *b = &bJump;
renderer->DrawRect(b->x,b->y,b->w,b->h);
if(curButt){
b = &bUse;
renderer->DrawRect(b->x,b->y,b->w,b->h);
}
if(player->weapon){
b = &bAttack;
renderer->DrawRect(b->x,b->y,b->w,b->h);
}
b = &bPause;
renderer->DrawRect(b->x,b->y,b->w,b->h);
glDisable(GL_BLEND);
renderer->SetColor(1,1,1,1);
}
if(settings.debugPhysics){
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
physics->world->debugDrawWorld();
renderer->SetColor(1,1,1,1);
//glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
}
}else{
menu.Draw(renderer);
}
renderer->Set2DMode();
//renderer->SetColor(1,1,1,1);
renderer->DrawText(strGameLog.c_str(),0,0.95,0.2);
CheckGLError("tpsGame::Draw", __FILE__, __LINE__);
}
Texture *GenerateStarBox(int size, int count){
GLubyte *starboxData = new GLubyte[size*size];
memset(starboxData,0,size*size);
/*starboxData[75]=255;
starboxData[130]=255;
starboxData[406]=255;
starboxData[625]=255;
starboxData[1307]=255;
starboxData[3506]=255;
starboxData[4002]=255;
starboxData[2383]=255;*/
for(int i=0;i<count;i++){
starboxData[glm::clamp((rand()*2)%(size*size),0,(size*size)-1)] = 255;
}
Texture *tex = new Texture();
tex->target = GL_TEXTURE_CUBE_MAP;
tex->Create(size,size);
tex->SetFilter(GL_LINEAR, GL_LINEAR);
for(int i=0; i<6; i++){
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, 0, GL_LUMINANCE, size,size, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, starboxData);
}
delete[] starboxData;
return tex;
}
Button::Button(float nx, float ny, float nw, float nh,bool adj):
x(nx),y(ny),w(nw),h(nh),type(0),text(0),active(true),pressed(false){
}
Button::Button(float nx, float ny, float nw, float nh, const char *t,bool adj):
x(nx),y(ny),w(nw),h(nh),type(0),text(t),active(true),pressed(false){}
bool Button::SetUniform(int loc){return false;}
void Button::Update(){}
void tpsGame::OnTouch(float x, float y, int ta, int tf){
float tx = x/renderer->width;
#ifdef ANDROID
float ty = (y-64)/renderer->height;
#else
float ty = y/renderer->height;
#endif
if(gameState==eGameMenu||gameState==eGamePause){
menu.OnTouch(tx,ty,ta,tf);
}
#ifdef ANDROID
else if(gameState==eGamePlay){
if(ta==IN_PRESS){
joyM.Hit(tx,ty,tf);
joyL.Hit(tx,ty,tf);
bJump.Hit(tx,ty);
bUse.Hit(tx,ty);
bAttack.Hit(tx,ty);
bPause.Hit(tx,ty);
for(uint32_t i=0; i<renderer->buttons.size();i++){
if(renderer->buttons[i]->active)
renderer->buttons[i]->Hit(tx,ty);
}
}else if(ta==IN_RELEASE){
joyM.Release(tf);
joyL.Release(tf);
bAttack.pressed = false;
}else if(ta==IN_MOVE){
joyM.Move(tx,ty,tf);
joyL.Move(tx,ty,tf);
joyL.vel.y*=-1;
}else{
Log("touch %d %d\n",ta, tf);
}
}
#endif
}
void tpsGame::OnMouseMove(float x, float y)
{
mousePos = vec2(x,y);
}
#ifndef ANDROID
#include <GLFW/glfw3.h>
void tpsGame::OnKey(int key, int scancode, int action, int mods)
{
if(gameState==eGamePlay){
keyM.OnKey(key,action);
if(action==GLFW_PRESS){
if(key==GLFW_KEY_ESCAPE){
PauseGame();
}
if(key==GLFW_KEY_SPACE){
bJump.pressed = true;
}
if(key==GLFW_KEY_E){
bUse.pressed = true;
}
}else if(action==GLFW_RELEASE){
}
}
}
#else
void tpsGame::OnKey(int key, int scancode, int action, int mods)
{
}
#endif