Uai ! em ateh map scroll hehehe, bem parte das minhas reflexões sobre a forma de implementar o jogo estão se materalizando, criei o conceito de cena, contendo o gerenciador de eventos e deslocamento da tela para permitir o scroll da tela de fundo.
o primeiro detalhe eh a classe Scene em si
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
namespace ChickenMaze
{
public abstract class Scene
{
public Game game;
public EventManager eventManager;
public int X;
public int Y;
public Scene(Game game, EventManager eventManager)
{
this.game= game;
this.eventManager= eventManager;
this.X = 0;
this.Y = 0;
}
public abstract void Initialize();
public abstract void LoadContent();
public abstract void Draw(GameTime gameTime, SpriteBatch spriteBatch);
}
}
que em alguns aspectos tentei manter o design semelhante a classe Game, com excessão do método Draw que adicionei o objeto spriteBatch sendo passado como parâmetro para evitar esta complexidade na cena atual, assim na classe Game principal do jogo um objeto scene é criado, e ao executar initialize, loadcontent e draw os respectivos metodos da Scene corrente serão chamados.
Esta abaixo eh a SceneMainMaze que determina os detalhes especificos do jogo, como sprite que vai ser usado como personagem, mapa e tratadores de eventos, note que a implementação dos eventos fica separada deste código.
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
namespace ChickenMaze
{
class SceneMainMaze : Scene
{
Sprite chicken;
Map map;
public SceneMainMaze(Game game, EventManager eventManager)
: base(game, eventManager)
{
}
public override void Initialize(){
map = new Map(this);
chicken = new Sprite(“chicken”, this);
chicken.Position = map.GetFirstFreeSpot();
chicken.SetMap(map);
eventManager.addHandler(new EventCantMoveHere(this));
eventManager.addHandler(new EventKeyboardLeft(this, chicken, map));
eventManager.addHandler(new EventKeyboardRight(this, chicken, map));
eventManager.addHandler(new EventKeyboardUp(this, chicken, map));
eventManager.addHandler(new EventKeyboardDown(this, chicken, map));
eventManager.addHandler(new EventNeedScrollMap(this, chicken, map ));
}
public override void LoadContent()
{
chicken.LoadContent(game.Content);
map.LoadContent(game.Content);
}
public override void Draw(GameTime gameTime, SpriteBatch spriteBatch)
{
Color color = new Color(0, 136, 0);
game.GraphicsDevice.Clear(color);
map.Draw(spriteBatch);
chicken.Draw(spriteBatch);
}
}
}
Então o trecho abaixo mostra como os eventos são registrados para que ao serem disparados, o tipo de evento é testado e em seguida o métido run() dos eventos é executado
eventManager.addHandler(new EventKeyboardDown(this, chicken, map));
eventManager.addHandler(new EventNeedScrollMap(this, chicken, map ));
O código abaixo é o tratador de eventos para quando o scroll de mapa eh necessário
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
namespace ChickenMaze
{
class EventNeedScrollMap: EventHandler
{
protected Sprite sprite;
protected Map map;
protected int HorizontalBorderLimit;
protected int VerticalBorderLimit;
const byte BORDER_DIVISION_INDEX = 4;
public EventNeedScrollMap(Scene scene, Sprite sprite, Map map)
: base(EventHandler.EventType.SPRITE_MOVED, scene)
{
this.sprite = sprite;
this.map = map;
HorizontalBorderLimit = scene.game.GraphicsDevice.Viewport.Width / BORDER_DIVISION_INDEX;
VerticalBorderLimit = scene.game.GraphicsDevice.Viewport.Height / BORDER_DIVISION_INDEX;
}
///
/// for each direction of the movement change the viewport
/// of the GraphicsDevice
///
/// public override void run(Object source) {
int SceneShift = sprite.speed;
int x = (int)sprite.Position.X – scene.X;
int y = (int)sprite.Position.Y – scene.Y;
// into left limit
if (x < scene.game.GraphicsDevice.Viewport.X + HorizontalBorderLimit)
{
if (scene.X - SceneShift > 0)
{
scene.X -= SceneShift;
}
}
// into right limit
if (x > scene.game.GraphicsDevice.Viewport.X
+ scene.game.GraphicsDevice.Viewport.Width – HorizontalBorderLimit)
{
scene.X += SceneShift;
}
// into top limit
if (y < scene.game.GraphicsDevice.Viewport.Y + VerticalBorderLimit)
{
if (scene.Y - SceneShift > 0)
{
scene.Y -= SceneShift;
}
}
// into bottom limit
if (y > scene.game.GraphicsDevice.Viewport.Y
+ scene.game.GraphicsDevice.Viewport.Height – VerticalBorderLimit)
{
scene.Y += SceneShift;
}
}
}
}
Desta maneira tratadores de evento podem ser facilmente reaproveitados entre jogos, e inclusive escrever código para realizar testes destes tratadores.
os próximos passos são :
- carregar o mapa de uma arquivo
- determinar que a galinha chegou no fim do mapa e criar evento para isto
- adicionar sons
- adicionar timer na tela
- adicionar os marcadores de labirinto com ovos (1 ovo a cada 10 segundos com duração de 60 segundos cada)
- adciionar cena de tela inicial
- adicionar cena de pontuação



