Muitas vezes queremos construir jogos mais complicados. Mas montar um jogo de labirinto por exemplo com o que voc� leu at� agora, n�o seria uma tarefa f�cil. Para isso n�s usamos um cen�rio.
No Jplay existe uma classe chamada Scene que � utilizada para a constru��o de cen�rios.
1 - Antes de come�ar a construir o c�digo
Antes de escrever qualquer linha de c�digo pense em como o seu cen�rio �, quais s�o as imagens est�ticas (n�o animadas), quais as imagens din�micas como sprites e animations. As imagens est�ticas ser�o as que estar�o inseridas no arquivo que comp�e a cena.
Tenha em mente que todas as imagens do cen�rio devem ter a mesma dimens�o, se voc� tem imagens que s�o ret�ngulos ent�o todas devem ser ret�ngulos.
Feito isso, voc� est� pronto para come�ar a constru��o do arquivo do seu cen�rio. As se��es 2 e 3 cuidam dessa constru��o.
2 - Organiza��o do arquivo do cen�rio
No Jplay as informa��es para a constru��o do cen�rio s�o quardadas em um arquivo com a extens�o '.scn'.
O arquivo � organizado da seguinte forma:
linha 1 - n�mero de imagens usadas para a constru��o do cen�rio (as imagens est�ticas).
linha 2 - caminho da primeira imagem e sua extens�o
linha 3 - caminho da segunda imagem e sua extens�o
linha 4 - caminho da terceira imagem e sua extens�o
linha n+1 - caminho da n-�sima imagem e sua extens�o
linha n+2 - come�o da constru��o da matriz
linha m - fim da constru��o da matriz que � representada pelo caracter '%'.
linha m+1 - caminho do backdrop e sua extens�o.
Obs.: N�o deixe nenhuma linha em branco pois, isso gerar� um erro de execu��o.
Exemplo de uma arquivo '.scn'.
- 3
- wall.jpg
- floor.jpg
- star.jpg
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0
- 0,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,0
- 0,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,0
- 0,1,2,1,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,1,0
- 0,1,2,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,2,2,2,1,0
- 0,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,0
- 0,1,2,1,1,1,1,2,2,2,1,1,1,1,1,1,2,2,1,1,1,2,1,0
- 0,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,1,0
- 0,1,2,1,2,2,2,1,2,2,2,2,2,2,2,1,1,1,1,1,2,2,1,0
- 0,1,2,1,2,2,2,1,1,1,1,1,1,1,2,1,2,2,2,1,2,2,1,0
- 0,1,2,1,2,2,2,2,2,2,1,2,2,2,2,1,2,2,2,1,1,1,1,0
- 0,1,2,1,2,2,2,2,2,2,1,2,2,2,2,1,2,2,2,2,2,2,1,0
- 0,1,2,1,1,1,2,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,0
- 0,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,3,0
- 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- %
- backdrop.jpg
3
wall.jpg
floor.jpg
star.jpg
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0
0,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,0
0,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,0
0,1,2,1,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,1,0
0,1,2,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,2,2,2,1,0
0,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,0
0,1,2,1,1,1,1,2,2,2,1,1,1,1,1,1,2,2,1,1,1,2,1,0
0,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,1,0
0,1,2,1,2,2,2,1,2,2,2,2,2,2,2,1,1,1,1,1,2,2,1,0
0,1,2,1,2,2,2,1,1,1,1,1,1,1,2,1,2,2,2,1,2,2,1,0
0,1,2,1,2,2,2,2,2,2,1,2,2,2,2,1,2,2,2,1,1,1,1,0
0,1,2,1,2,2,2,2,2,2,1,2,2,2,2,1,2,2,2,2,2,2,1,0
0,1,2,1,1,1,2,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,0
0,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,3,0
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
%
backdrop.jpg
3 - Construindo a matriz
A matriz � composta por n�meros inteiros separados por virgula e sem espa�os entre eles.
O n�mero 0 (zero) sempre corresponde ao backdrop (a imagem que ser� desenhada por baixo do cen�rio).
J� os outros n�mero seguem a seguinte l�gica:
1 - representa a imagem wall.jpg
2 - representa a imagem flor.jpg
3 - representa a imagem star.jpg
Colocamos o n�mero 0 (zero) nas bordas sinalizando que essa � uma �rea do backdrop.
O n�mero 1 � usado como 'wall' e delimita passagens.
O n�mero 2 � usado como lugares pecorr�veis.
O n�mero 3 � usado como ponto final de chegada.
4 - Construindo o c�digo para mostrar um cen�rio
Para construir o c�digo n�s usaremos os seguintes m�todos da classe Scene:
-
- public Scene();
-
-
- public void loadFromFile(String fileName);
-
-
- public void setDrawStartPos(int drawStartX, int drawStartY);
-
-
- public void draw();
-
//Construtor da classe
public Scene();
//Ccarrega as informa��es armazenadas no arquivo '.scn'.
public void loadFromFile(String fileName);
//Informa ao Jplay quais s�o as coordenadas iniciais onde o cen�rio dever� ser desenhado inicialmente.
public void setDrawStartPos(int drawStartX, int drawStartY);
//Desenha o cen�rio na tela
public void draw();
Exemplo: Mostrando um cen�rio na tela.
- package cenario;
-
- import java.awt.Point;
- import java.util.Vector;
- import jplay.Keyboard;
- import jplay.Scene;
- import jplay.TileInfo;
- import jplay.Window;
-
-
-
-
-
-
-
- public class Cenario {
-
- private Window window;
- private Scene scene;
-
- public Cenario()
- {
- window = new Window(800,600);
- scene = new Scene();
- scene.loadFromFile("scene.scn");
- scene.setDrawStartPos(15, 30);
-
- }
-
- public void run()
- {
- while(true)
- {
- scene.draw();
- window.update();
- }
- }
-
-
-
-
- public static void main(String[] args) {
- Cenario cen = new Cenario();
- cen.run();
- }
- }
-
package cenario;
import java.awt.Point;
import java.util.Vector;
import jplay.Keyboard;
import jplay.Scene;
import jplay.TileInfo;
import jplay.Window;
/**
* @author Gefersom Cardoso Lima
* Federal Fluminense University
* Computer Science
*/
public class Cenario {
private Window window;
private Scene scene;
public Cenario()
{
window = new Window(800,600);
scene = new Scene();
scene.loadFromFile("scene.scn");
scene.setDrawStartPos(15, 30);
}
public void run()
{
while(true)
{
scene.draw();
window.update();
}
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Cenario cen = new Cenario();
cen.run();
}
}
5 - Adicionando um objeto ao cen�rio.
Para adicionar um objeto que ser� controlado por n�s ao cen�rio usamos o m�todo abaixo:
-
-
- public void addOverlay(GameObject overlay);
-
//Adiciona qualquer GameObject do Jplay ao cen�rio mas, n�o modifica a
//matriz que � usada para a constru��o do cen�rio.
public void addOverlay(GameObject overlay);
Com o m�todo acima podemos adicionar um GameImage, uma Animation ou um Sprite ao cen�rio.
6 - A classe auxiliar TileInfo.
Quando o Jplay l� o arquivo de entrada do cen�rio ele cria para cada valor inteiro da matriz armazenada no arquivo '.scn' um TileInfo.
As informa��es armazenadas no TileInfo s�o: 'id' - valor num�rico que representa a imagem e uma refer�ncia para a imagem.
Todos os TileInfos s�o armazenados em um matriz usada internamente pela classe Scene.
Exemplo:
A imagem 'wall.jpg' � presentando pelo n�mero 1.
O Jplay cria um TileInfo com a ID = 1 e associa esse TileInfo a imagem 'wall.jpg' que � armazenada em outra estrutura interna na classe Scene.
� por meio do TileInfo que podemos saber onde um determinado overlay est� localizado e quais s�o as imagens sobrepostas por ele ou em volta dele.
7 - Delimitando �reas pecorr�veis.
M�todo da classe Scene usados nessa se��o:
-
- public Vector getTilesFromRect(Point min, Point max)
//Retorna os objetos que est�o entre os ponto passados como par�metros.
public Vector getTilesFromRect(Point min, Point max)
Se n�o delimitarmos �reas em que o GameObject (adicionado com o m�todo addOverlay()) pode percorrer ele se mover� por todo o cen�rio.
Para fazer o GameObject se mover somente por algumas �reas seguimos os seguinte passos:
1 - Capturamos os valores m�nimos e m�ximos para as coordenadas do GameObject.
-
-
-
-
- Point playerMin = new Point ((int)gameObject.x, (int)gameObject.y);
-
-
- Point playerMax = new Point((int)(gameObject.x + player.width), (int)(gameObject.y + gameObject.height));
//Lembre-se que as coordenadas de todo GameObject no Jplay s�o n�meros no formato 'double'
//logo, algumas vezes precisaremos fazer um cast para um n�mero inteiro.
//Posicao min � a posi��o (x,y) do GameObject
Point playerMin = new Point ((int)gameObject.x, (int)gameObject.y);
//Posicao max � a posi��o (x + largura, y + altura) do GameObject
Point playerMax = new Point((int)(gameObject.x + player.width), (int)(gameObject.y + gameObject.height));
2 - Capturamos as imagens que est�o na mesma �rea do GameObject.
-
- Vector tiles = scene.getTilesFromRect(playerMin, playerMax);
//Retorna as imagens que estiverem na mesma �rea do GameObject (x,y), (x + largura, y + altura)
Vector tiles = scene.getTilesFromRect(playerMin, playerMax);
3 - Para cada tile retornado verificamos qual � o tile a partir da sua id e se o player colidiu com ele.
Depois do teste de colis�o e de verifica��o de id o que ser� feito � uma escolha do programador.
No trecho abaixo o GameObject somente � reposicionado alguns pixels. J� que para haver uma colis�o alguns pixels t�m que ser sobrepostos. Caso n�o fizessemos isso o GameObject ficaria colidindo infinitamente com o TileInfo.
-
- for(int i = 0 ; i < tiles.size() ; i++)
- {
- TileInfo tile = (TileInfo)tiles.elementAt(i);
-
-
- if((tile.id == Constante.TILE_WALL) && player.collided(tile))
- {
-
- if (player.moveuNaHorizontal())
- {
-
- if(player.x <= tile.x -1)
- player.x = tile.x - player.width;
- else
-
- player.x = tile.x + tile.width;
- }
- else
- {
- if(player.y >= tile.y + tile.height -1)
- player.y = tile.y + tile.height;
- else
-
- player.y = tile.y - player.height ;
- }
- return false;
- }
- else
-
- if(tile.id == Constante.TILE_STAR)
- return true;
- }
- return false;
-
//para todos os tiles
for(int i = 0 ; i < tiles.size() ; i++)
{
TileInfo tile = (TileInfo)tiles.elementAt(i);
//se o tile � parede e o player colidiu com ele
if((tile.id == Constante.TILE_WALL) && player.collided(tile))
{
//se o player est� se movendo na diagonal
if (player.moveuNaHorizontal())
{
//o player est� atr�s da parede?
if(player.x <= tile.x -1)
player.x = tile.x - player.width;//Reposiciona o player
else
//o player est� na frente da parede
player.x = tile.x + tile.width;//Reposiciona o player
}
else
{ //o player est� abaixo da parede?
if(player.y >= tile.y + tile.height -1)
player.y = tile.y + tile.height;//Reposiciona o player
else
//o player est� acima da parede
player.y = tile.y - player.height ;//Reposiciona o player
}
return false;
}
else
//se o player encontrou a estrela
if(tile.id == Constante.TILE_STAR)
return true;
}
return false;
}
Exemplo:
import jplay.Keyboard;
import jplay.Sprite;
import java.awt.Point;
import java.util.Vector;
import jplay.Keyboard;
import jplay.Scene;
import jplay.TileInfo;
import jplay.Window;
/*----------------------------------------------------------------------------------------------*/
public class Constante
{
public static int TILE_WALL = 1;
public static int TILE_STAR = 3;
}
/*----------------------------------------------------------------------------------------------*/
public class Player extends Sprite
{
private boolean horizontalMoveKeyPressed;
public Player()
{
super("player.png",8);
}
public boolean moveuNaHorizontal()
{
return horizontalMoveKeyPressed;
}
public void move(Keyboard keyboard)
{
horizontalMoveKeyPressed = true;
if(keyboard.keyDown(Keyboard.LEFT_KEY) == true)
{
this.x -= 1;
setCurrFrame(2);
}
else
if(keyboard.keyDown(Keyboard.RIGHT_KEY) == true)
{
this.x += 1;
setCurrFrame(3);
}
else
horizontalMoveKeyPressed = false;
if (!horizontalMoveKeyPressed)
{
if(keyboard.keyDown(Keyboard.UP_KEY) == true)
{
this.y -= 1;
setCurrFrame(0);
}
else
if(keyboard.keyDown(Keyboard.DOWN_KEY) == true)
{
this.y += 1;
setCurrFrame(1);
}
}
}
}
/*----------------------------------------------------------------------------------------------*/
public class Cenario
{
private Window window;
private Keyboard keyboard;
private Scene scene;
private Player player;
public Cenario()
{
window = new Window(800,600);
keyboard = window.getKeyboard();
scene = new Scene();
scene.loadFromFile("scene.scn");
scene.setDrawStartPos(15, 30);
player = new Player();
player.x = 454;
player.y = 140;
scene.addOverlay(player);
}
public void run()
{
boolean loop = true;
while(loop)
{
draw();
controlarCaminho();
player.move(keyboard);
if (keyboard.keyDown(Keyboard.ESCAPE_KEY))
loop = false;
window.delay(10);
}
window.exit();
}
public void draw()
{
scene.draw();
window.update();
}
boolean controlarCaminho()
{
//Posicao min � a posi��o (x,y) do player
//Posicao max � a posi��o (x + largura, y + altura) do player
Point playerMin = new Point ((int)player.x, (int)player.y);
Point playerMax = new Point((int)(player.x + player.width), (int)(player.y + player.height));
//Retorna as imagens que estiverem na mesma �rea do player (x,y), (x + largura, y + altura)
Vector tiles = scene.getTilesFromRect(playerMin, playerMax);
//para todos os tiles
for(int i = 0 ; i < tiles.size() ; i++)
{
TileInfo tile = (TileInfo)tiles.elementAt(i);
//se o tile � parede e o player colidiu com ele
if((tile.id == Constante.TILE_WALL) && player.collided(tile))
{
//se o player est� se movendo na diagonal
if (player.moveuNaHorizontal())
{
//o player est� atr�s da parede?
if(player.x <= tile.x -1)
player.x = tile.x - player.width;//Reposiciona o player
else
//o player est� na frente da parede
player.x = tile.x + tile.width;//Reposiciona o player
}
else
{ //o player est� abaixo da parede?
if(player.y >= tile.y + tile.height -1)
player.y = tile.y + tile.height;//Reposiciona o player
else
//o player est� acima da parede
player.y = tile.y - player.height ;//Reposiciona o player
}
return false;
}
else
//se o player econtrou a estrela
if(tile.id == Constante.TILE_EXIT)
return true;
}
return false;
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Cenario cen = new Cenario();
cen.run();
}
}
8 - Todos os m�todos da classe Scene.
-
- public Scene();
-
-
- public void loadFromFile(String sceneFile);
-
-
-
- public void addOverlay(GameObject overlay);
-
-
- public void setDrawStartPos(int drawStartX, int drawStartY);
-
-
- public void draw();
-
-
-
- public TileInfo getTile(int row, int colunm);
-
-
- public Vector getTilesFromRect(Point min, Point max);
-
-
-
- public Vector getTilesFromPosition(Point min, Point max);
-
-
- public void removeTile(int row, int colunm);
-
-
- public void changeTile(int row, int colunm, int newID);
-
-
- public void saveToFile(String fileName);
-
-
- public void moveScene(GameObject object);
-
-
- public double getXOffset();
-
-
- public double getYOffset();
-
//Construtor da classe
public Scene();
//Carrega as informa��es armazenadas no arquivo '.scn'.
public void loadFromFile(String sceneFile);
//Adiciona qualquer GameObject do Jplay ao cen�rio mas, n�o modifica a
//matriz que � usada para a constru��o do cen�rio.
public void addOverlay(GameObject overlay);
//Informa ao Jplay quais s�o as coordenadas iniciais onde o cen�rio dever� ser desenhado inicialmente.
public void setDrawStartPos(int drawStartX, int drawStartY);
//Desenha o cen�rio na tela
public void draw();
//Retorna um tile da matrix de tiles especificado pela sua linha e coluna na matrix,
//caso a linha ou a coluna n�o existam retorn null.
public TileInfo getTile(int row, int colunm);
//Retorna os objetos que est�o entre os ponto passados como par�metros.
public Vector getTilesFromRect(Point min, Point max);
//Retorna os objetos que est�o entre os ponto passados como par�metros
//(deve ser usado em substitui��o � fun��o anterior, em jogos do tipo side scrolling).
public Vector getTilesFromPosition(Point min, Point max);
//Remove um tile da matrix de tiles especificado pela sua linha e coluna na matrix.
public void removeTile(int row, int colunm);
//Troca a ID do tile especificado pela sua linha e coluna pela ID de um outro tile.
public void changeTile(int row, int colunm, int newID);
//Salva o estado corrente da Scene em arquivo para posterior recupera��o, os overlays n�o ser�o salvos.
public void saveToFile(String fileName);
//Move o cenario de forma a centralizar o object passado como par�metro.
public void moveScene(GameObject object);
//Retorna a �ltima movimenta��o do cen�rio no eixo x.
public double getXOffset();
//Retorna a �ltima movimenta��o do cen�rio no eixo y.
public double getYOffset();