using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
namespace TileEngine
{
class Renderer : DrawableGameComponent
{
SpriteBatch spriteBatch;
public Renderer(Game game)
: base(game)
{
// TODO: Construct any child components here
}
protected override void LoadContent()
{
// base.LoadContent();
}
public override void Draw(GameTime gameTime)
{
base.Draw(gameTime);
}
public override void Update(GameTime gameTime)
{
base.Update(gameTime);
}
public override void Initialize()
{
base.Initialize();
}
public RenderTarget2D new_texture(int width, int height)
{
Texture2D TEX = new Texture2D(GraphicsDevice, width, height); //create the texture to render to
RenderTarget2D Mine = new RenderTarget2D(GraphicsDevice, width, height);
GraphicsDevice.SetRenderTarget(Mine); //set the render device to the reference provided
//maybe base.draw can be used with spritebatch. Idk. We'll see if the order of operation
//works out. Wish I could call base.draw here.
return Mine; //I'm hoping that this returns the same instance and not a copy.
}
public void draw_texture(int width, int height, RenderTarget2D Mine)
{
GraphicsDevice.SetRenderTarget(null); //Set the renderer to render to the backbuffer again
Rectangle drawrect = new Rectangle(0, 0, width, height); //Set the rendering size to what we want
spriteBatch.Begin(); //This uses spritebatch to draw the texture directly to the screen
spriteBatch.Draw(Mine, drawrect, Color.White); //This uses the color white
spriteBatch.End(); //ends the spritebatch
//Call base.draw after this since it doesn't seem to recognize inside the function
//maybe base.draw can be used with spritebatch. Idk. We'll see if the order of operation
//works out. Wish I could call base.draw here.
}
public GraphicsDevice myDevice { get; set; }
}
}
I still can't call this class as an object in XNA
Here is the working code in the initialize function where I try to create it. But in my draw code it still doesn't let me go:
tileclipping.draw_texture(...);
Here's the full code from game1
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using TileEngine;
namespace TileEngine
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
public GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
TileMap myMap = new TileMap();
int squaresAcross = 12;
int squaresDown = 12;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
// tileClipping = new Renderer();
// TODO: Add your initialization logic here
Renderer tileclipping = new Renderer(this) ;
//Components.Add(tileclippping);
base.Initialize();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
Tile.TileSetTexture = Content.Load<Texture2D>(@"Textures\TileSets\part1_tileset");
// TODO: use this.Content to load your game content here
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
KeyboardState ks = Keyboard.GetState();
if (ks.IsKeyDown(Keys.Left))
{
Camera.Location.X = MathHelper.Clamp(Camera.Location.X - 8, 0, (myMap.MapWidth - squaresAcross) * 32);
}
if (ks.IsKeyDown(Keys.Right))
{
Camera.Location.X = MathHelper.Clamp(Camera.Location.X + 8, 0, (myMap.MapWidth - squaresAcross) * 32);
}
if (ks.IsKeyDown(Keys.Up))
{
Camera.Location.Y = MathHelper.Clamp(Camera.Location.Y - 8, 0, (myMap.MapHeight - squaresDown) * 32);
}
if (ks.IsKeyDown(Keys.Down))
{
Camera.Location.Y = MathHelper.Clamp(Camera.Location.Y + 8, 0, (myMap.MapHeight - squaresDown) * 32);
}
// TODO: Add your update logic here
base.Update(gameTime);
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
//use the instance of renderer called tileclipping to generate a new texture of a specified size for tiles
//this surface is 200 pixels by 200 pixels for the reason that it's the same as the clipping i'll choose
Texture2D mytexture = new Texture2D(GraphicsDevice, 200, 200);
RenderTarget2D Mine = new RenderTarget2D(graphics.GraphicsDevice, 200, 200);
//Mine = tileclipping.new_texture(200, 200);
spriteBatch.Begin();
Vector2 firstSquare = new Vector2(Camera.Location.X / 32, Camera.Location.Y / 32);
int firstX = (int)firstSquare.X;
int firstY = (int)firstSquare.Y;
Vector2 squareOffset = new Vector2(Camera.Location.X % 32, Camera.Location.Y % 32);
int offsetX = (int)squareOffset.X;
int offsetY = (int)squareOffset.Y;
for (int y = 0; y < squaresDown; y++)
{
for (int x = 0; x < squaresAcross; x++)
{
spriteBatch.Draw(
Tile.TileSetTexture,
new Rectangle((x * 32) - offsetX, (y * 32) - offsetY, 32, 32),
Tile.GetSourceRectangle(myMap.Rows[y + firstY].Columns[x + firstX].TileID),
Color.White);
}
}
spriteBatch.End();
// TODO: Add your drawing code here
//There are two instances of mine
//A new one is made each time tileclipping.new_texture is called
//This function can re use the copy created by new texture
//hopefully this saves on memory
base.Draw(gameTime);
}
public CubeMapFace Tex2d { get; set; }
internal Renderer tileClipping { get; set; }
public IGameComponent tileclippping { get; set; }
}
}
I'm sorry if it isn't clear what i'm trying to do. I'm trying to capture a 2d texture (or create one) OUTSIDE my game class I'm trying to use a class as a handler, to pass these texture2d's back and forth between GAME1 and my Renderer I don't WANT to have all my textures inside my main class. Also another thing with this is that I'm trying to basically have a generic texture2d CREATOR.
Aka this isn't for something simple like rendering sprites. The function of RENDERER is to either create a new TEXTURE2D object with a NEW render target object based on parameters fed to this function:
public RenderTarget2D new_texture(int width, int height)
{
Texture2D TEX = new Texture2D(GraphicsDevice, width, height); //create the texture to render to
RenderTarget2D Mine = new RenderTarget2D(GraphicsDevice, width, height);
GraphicsDevice.SetRenderTarget(Mine); //set the render device to the reference provided
//maybe base.draw can be used with spritebatch. Idk. We'll see if the order of operation
//works out. Wish I could call base.draw here.
return Mine; //I'm hoping that this returns the same instance and not a copy.
}
I need a way of creating a copy of the renderer class WITHOUT having it in the gamecomponents list. The reason is because XNA won't let me access Graphics device, which is a required parameter OF a texture2D object. So basically i'm doing all this stuff as a work around just becuase Texture2D requires graphics device as a parameter and I can't willy nilly pass GraphicsDevice INTO an instance of my renderer class i've already tried that and it fails.
So there will be situations in my game where say
if (Camera_zoom==1){
scaling_texture.dispose();
scaling_texture = tileclipping.new_texture(camera_width*camera_zoom, camera_height*camera_zoom);
// call a refresh command here
this.refresh_scene(...) //Inside here is a ton of sprite batches because the render target is now set to NEW scaling_texture
//after that we do the drawing using spritebatch inside draw function of main game class
//expecting that a render texture is provided for us by these pre requisites.
//then after that we call the render command
//it returns the render target to the screen
//then in the draw command AFTER the sprite batches were drawn TO the target surface called scaling_texture
//We use various parameters to tell it to draw this scaling_texture as a spritebatch.draw() inside the
//game1 draw class
//So basically I want to do things in this order
/// Create new texture of variable size
// use it as render target
// Do all my spritebatch
// call another spritebatch
//draw the contents of said texture on the screen as the rendering target
//Dispose of the texture object
//Check the scaling size of it
//Re create the scaling texture with a NEW resolution (each frame)
//Select it as a render target
//Do the spritebatchy stuff all over again repeat above for all game loop
//BUT I want parts of this, mainly the creation of this Texture2D object, and the drawing of it to the backbuffer
//To all happen inside my Renderer class
//but for all main game spritebatches to happen inside my main game class
//This is a problem for me and XNA doesn't seem to want to let me organize it this way
//Unless i'm missing something which is why i'm making this lengthy post
//ANY and all help is appreciated.
//Thanks again and I hope I explained myself well enough this time IE my intentions.
//PLEASE NOTE I am SET on doing things THIS way. I will NEED a texture 2d rendering target that is NON static
//During MOST of my GAME project.
//That said.. IT HAS TO have function to wrap it inside Renderer. THere is no way in hell I'm going to do this
//In a spaghetti code fashion Inside GAME1 with nested if statements.
//Thanks all
}