Estou desenvolvendo um jogo,que vai ser feito em Opengl, minha duvida é como fazer a transição de fases, não gostaria de fechar e abrir novamente a janela, (que é um objeto do tipo Display), pois ela demora muito para abrir e quebraria o clima do jogo.
Já tinha pensado em varia maneira de resolver mais nenhuma delas funcionou.
Detalhes de como o sistema funciona:
O sistema carrega vários cenários, personagens e textos em uma fase, para a fase não ficar pesada é limitado o numero de cenários.
Durante o jogo um algoritmo cria vários personagem completamente novos o que exige uma atualização no buffer de imagem do opengl, por isso o sistema de fases é necessário assim não preciso carregar todos os personagem e ao mesmo tempo só uso os necessários, já implementei essa parte, o problema e que não consigo fazer o display setar.
Inicialmente eu tentei fazer um sistema como o de baixo
Mas o algoritmo não funciona quando volta pelo loop principal.
Então tentei chamar a janela por uma classe externa o problema e que não posso substituir o display isso me obrigaria a fechar o display e abrir outro, e não gostaria que a cada loadding a janela ficasse fechando e abrindo.
Como os personagens são criados randomicamente e não da para carregar todos os personagens uma vez durante o jogo, e não seria legar ficar pedindo para usuário fechar o jogo para atualizar
É difícil dizer qual o seu problema ao certo, mas está tentando usar mais de um loop? Por que não tenta diferentes estados, dentro de um loop único, usando uma máquina de estados? Assim, o estado de menu, loading e de jogo teriam seu próprio renders, updates e sincronizes.
Em pseudocódigo, ficaria algo como:
class State{
Game game;
void State(Game game){
this.game = game;
}
abstract void update(deltaTime);
abstract void render();
}
class LoadState extends State{
boolean loaded = false;
void update( deltaTime ){
// carrega um ou mais recurso a cada ciclo, de preferência numa thread separado
// quando concluir, mande uma mensagem à classe principal para carregar o próximo estado
while (! loaded){
// carrega algo
}
game.setNextState(new PlayState());
}
void render(){
// exibe mensagem: carregando
}
}
class PlayStateextends State{
void update( deltaTime ){
// atualiza objetos do mapa/fase/cenário
}
void render(){
// exibe a fase
}
}
Você pode usar os estados no seu loop principal. A transição entre estados pode ser feita através de um gerenciador, ou mesmo cada estado sendo capaz de enviar uma mensagem à classe principal dizendo qual o próximo estado (método setNextState da classe abaixo).
class Game{
boolean finished = false;
State current = nil;
void run(){ // gameloop
current = new LoadState(this);
while (! finished){
current.update(delta);_
sincronize(60);_
current.render();_
}
}
void setNextState(State state){
this.current = state;
}
}
Leia sobre máquinas de estado em: https://pt.slideshare.net/AndreKishimoto/mquina-de-estados-controlando-o-jogo-do-menu-ia
Abraço.
A ideia foi boa, meu problema nesse caso esta no loaddata, essa função carrega as texturas processadas através do opengl nesse caso.
o método de buffer da imagens para o opengl só esta funcionado na primeira ocorrência, mesmo que fizesse por chamada não carregaria as imagens no próximo momento da maquina de estados por isso pensei em trocar a janela, para tentar evitar esse problema que não funcionar o carregamento da textura na fase seguinte.
o Display é a classe de janela que uso, seria equivalente ao jframe, o problema da estrutura de loop e por causa justamente da maquina de estados, tipo vo mostra uma pouco do código para entenderem melhor:
}
systemPathConfigure(); //Pega os dados de janelas do SO
configureDisplay(); //Configura a janela
initOpenGl(); //Configura o OpenGL
changeBackGroundColor("#ebccb6");
while(config.isGame_on()){
switch(this.config.getFase_atual()){
case 0:
jogo = new Intro(this);
break;
case 1:
jogo = new Casa(this);
break;
}
//Aqui carrego a textura da fase
if(jogo.modeinit()[0]){
List<Font> rnd1 = jogo.fontinit();
//new Log(rnd1.get(0).getFonts().get(0));
for(int a = 0; a<rnd1.size();a++){
ar = rnd1.get(a).getCod(0);
img = Image.GetImage(FontFile.main().get(ar[0])+FontFile.main(false).get(0));
rnd1.get(a).setSep(FontFile.main(ar[0]));
for(int b=0;b<rnd1.get(a).size();b++){
if(img != null){
ar = rnd1.get(a).getCod(b);
id = Image.Image(img,
ar[1],
ar[2],
ar[3],
ar[4],
true,
rnd1.get(a).getCor()
);
rnd1.get(a).setId(b, id);
}
}
}
}
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
jogo.init();
glEnable(GL_TEXTURE_2D); //Enable texturing
while(config.isFase_on()){
if(Display.isCloseRequested()){ //Fecha o jogo
config.setFase_on(false);
config.setGame_on(false);
}
glClear(GL_COLOR_BUFFER_BIT);
//Enable blending so the green background can be seen through the texture
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
jogo.render();
glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
//rect(0, 0, 32, 32, charpter.g);
jogo.update();
Display.update();
Display.sync(60);
}
}
}
Desculpe pela bagunça mais não aparecem botão para inserir código
Bem acabei encontrando um jeito destruindo a janela e reconstruindo, agradeço a ajuda.
Minha solução ficou assim:
while(game_on){
try{
Display.create();
}catch(IOException e){
//
}
//executa a fase
…
Diplay.destroy();
}