I'm rather new at monogame and I've ran into yet another issue that I can't seem to figure out. After a few other issues (that have been resolved by you amazing people!) I've ran into another!
I can't seem the figure out why my mobs won't spawn, everything else spawns and works as it should but the enemies will not spawn. I'm relatively new at this so I haven't really tried anything but looking online at tutorials to see if ive done it correctly but I cannot see what I have done wrong.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Content;
namespace Roid_shoooota
{
public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
//player and BG stuff
PlayerShip Player = new PlayerShip();
Background bG = new Background();
//asteroid stuff
List<Roids> asteroidList = new List<Roids>();
Random random = new Random();
//mob stuff
public int enemyBulletDamage;
List<Mobs> mobsList = new List<Mobs>();
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.IsFullScreen = false;
graphics.PreferredBackBufferWidth = 800;
graphics.PreferredBackBufferHeight = 950;
this.Window.Title = "Roid Shoota";
enemyBulletDamage = 10;
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
Player.LoadContent(Content);
bG.LoadContent(Content);
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
//updating mobs and checking for collisions
foreach (Mobs M in mobsList)
{
if (M.hitBox.Intersects(Player.boundingBox))
{
Player.health -= 40;
M.isVisible = false;
}
//enemy bullet collision with player
for (int i = 0; i < M.bulletList.Count; i++)
{
if (Player.boundingBox.Intersects(M.bulletList[i].hitBox))
{
Player.health -= enemyBulletDamage;
M.bulletList[i].isVisible = false;
}
}
for (int i = 0; i < Player.bulletList.Count; i++)
{
if (Player.bulletList[i].hitBox.Intersects(M.hitBox))
{
Player.bulletList[i].isVisible = false;
M.isVisible = false;
}
}
M.update(gameTime);
}
//updating the asteroid list, check for collisions
foreach (Roids R in asteroidList)
{
//if a roid hits the player get oot me game
if (R.hitBox.Intersects(Player.boundingBox))
{
Player.health -= 20;
R.isVisible = false;
}
for (int i = 0; i < Player.bulletList.Count; i++)
{
if (R.hitBox.Intersects(Player.bulletList[i].hitBox))
{
R.isVisible = false;
Player.bulletList.ElementAt(i).isVisible = false;
}
}
R.update(gameTime);
}
Player.update(gameTime);
bG.update(gameTime);
loadAsteroids();
loadMobs();
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
bG.Draw(spriteBatch);
Player.draw(spriteBatch);
foreach (Roids R in asteroidList)
{
R.Draw(spriteBatch);
}
foreach (Mobs M in mobsList)
{
M.Draw(spriteBatch);
}
spriteBatch.End();
base.Draw(gameTime);
}
//random roid spawns
public void loadAsteroids()
{
int randY = random.Next(-600, -50);
int randX = random.Next(0, 750);
//create more if less than 5
if(asteroidList.Count() < 40)
{
asteroidList.Add(new Roids(Content.Load<Texture2D>("asteroid"), new Vector2(randX, randY)));
}
//if destoryed or off screen remove it from da list
for (int i = 0; i < asteroidList.Count; i++)
{
if (!asteroidList[i].isVisible)
{
asteroidList.RemoveAt(i);
i--;
}
}
}
//load mobs
public void loadMobs()
{
int randY = random.Next(-600, -50);
int randX = random.Next(0, 750);
//create more if less than 3
if (mobsList.Count() < 3)
{
mobsList.Add(new Mobs(Content.Load<Texture2D>("enemyship"), new Vector2(randX, randY), Content.Load<Texture2D>("EnemyBullet")));
}
//if destoryed or off screen remove it from da list
for (int i = 0; i < mobsList.Count; i++)
{
if (!mobsList[i].isVisible)
{
mobsList.RemoveAt(i);
i--;
}
}
}
}
}
Related
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
public class GetChildsEditorWindow : EditorWindow
{
public Transform transform;
int levelsMin = 0, levelsMax = 50;
static int currentLevel;
List<Transform> allChildren = new List<Transform>();
static int oldLevel = 0;
// Add menu named "My Window" to the Window menu
[MenuItem("Get Childs/Get")]
static void Init()
{
oldLevel = currentLevel;
// Get existing open window or if none, make a new one:
GetChildsEditorWindow window = (GetChildsEditorWindow)EditorWindow.GetWindow(typeof(GetChildsEditorWindow), false, "Get Childs");
window.Show();
}
private void OnGUI()
{
GUILayout.Space(20);
transform = EditorGUILayout.ObjectField("Transform to get childs", transform, typeof(Transform), true) as Transform;
EditorGUI.BeginDisabledGroup(transform == null);
currentLevel = (int)EditorGUILayout.Slider("Slider", currentLevel, levelsMin, levelsMax);
EditorGUI.EndDisabledGroup();
if (allChildren != null && allChildren.Count > 0)
{
for (int i = 0; i < allChildren.Count; i++)
{
allChildren[i] = EditorGUILayout.ObjectField("Transform " + i.ToString(), allChildren[i], typeof(Transform), true) as Transform;
}
}
if (oldLevel != currentLevel)
{
if (transform != null)
{
allChildren = new List<Transform>();
IterateOverChild(transform, currentLevel, levelsMax);
oldLevel = currentLevel;
}
}
}
public void IterateOverChild(Transform original, int currentLevel, int maxLevel)
{
if (currentLevel > maxLevel) return;
for (var i = 0; i < original.childCount; i++)
{
Debug.Log($"{original.GetChild(i)}"); //Do with child what you need
allChildren.Add(original.GetChild(i));
IterateOverChild(original.GetChild(i), currentLevel + 1, maxLevel);
}
}
}
The script is working as i wanted , the question is if calling the loop inside the OnGUI is a bad practice performance ? because it's working fine i just wonder if it's wrong to have a loop inside the OnGUI.
I am currently making a tile-based game in c#, but every time I draw the tiles it uses a lot of CPU, and as the tiles get bigger(if i make the game full screen) it consumes even more.
This is my Tile class:
public class Tiles
{
//PRIVATE :
//variabiles
private int XPosition, YPosition;
private Image Texture;
private bool Colidable;
private int SizeW = 32;
private int SizeH = 32;
private Resizer resizer = new Resizer();
//methods
//PUBLIC :
//variabiles
//methods
//CONSTRUCTOR
public Tiles(int _x,int _y,Image _i, int _sW = 32, int _sH = 32, bool _c = false)
{
XPosition = _x;//set position X
YPosition = _y;//set position Y
SizeW = _sW;
SizeH = _sH;
Texture = resizer.ResizeImage(_i, SizeW, SizeH) ;// set texture
Colidable = _c;//set if the tile is colidable,default : false
resizer = null;
}
//DRAW METHOD
//gets graphics object to draw on, adn draws at the position of the tile
public void Draw(Graphics _g)
{
_g.DrawImage(this.Texture, this.XPosition, this.YPosition);
}
//GET PRIVATE MEBERS
//returns if the tile is colidable
public bool getColidable()
{
return this.Colidable;
}
}
and this is how I draw the tiles:
private void DrawMap(Graphics _g)
{
//CALLS THE DRAW METHOD OF EACH TILE
for (int i = 0; i < MAP_WIDTH; i++)
{
for (int j = 0; j < MAP_HEIGHT; j++)
{
Tile[i, j].Draw(_g);
}
}
}
bool TilesUpdate = false;
private void _Window_Paint(object sender, PaintEventArgs e)
{
e.Graphics.Clear(Color.Black);
if (isGameRunning)
{
DrawMap(e.Graphics);
}
else
{
FullRezolutionBtn.Draw(e.Graphics);
BigRezolutionBtn.Draw(e.Graphics);
NormalRezolutionBtn.Draw(e.Graphics);
}
}
private void Update_Tick(object sender, EventArgs e)
{
Invalidate();
}
I want to mention that the map is 20 x 20 tiles and it's cosuming around 50% of the cpu when it's fullscreen.
As I mentioned in the comments, the direction should be to do less painting. One way is to invalidate and paint portions of the drawing canvas only when something related to that portion changes. Windows itself does such optimization for controls/windows.
Here is an example. Look how Gadget class invalidates it's rectangle when some property changes. Then during the paint, only rectangles that intersect with e.ClipRectange are drawn. This highly reduces the number of the drawing operations.
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Samples
{
class Gadget
{
public readonly Control Canvas;
public Gadget(Control canvas) { Canvas = canvas; }
private Rectangle bounds;
public Rectangle Bounds
{
get { return bounds; }
set
{
if (bounds == value) return;
// NOTE: Invalidate both old and new rectangle
Invalidate();
bounds = value;
Invalidate();
}
}
private Color color;
public Color Color
{
get { return color; }
set
{
if (color == value) return;
color = value;
Invalidate();
}
}
public void Invalidate()
{
Canvas.Invalidate(bounds);
}
public void Draw(Graphics g)
{
using (var brush = new SolidBrush(color))
g.FillRectangle(brush, bounds);
}
}
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var form = new Form { WindowState = FormWindowState.Maximized };
int rows = 9, cols = 9;
var gadgets = new Gadget[rows, cols];
var rg = new Random();
Color[] colors = { Color.Yellow, Color.Blue, Color.Red, Color.Green, Color.Magenta };
int size = 64;
var canvas = form;
for (int r = 0, y = 8; r < rows; r++, y += size)
for (int c = 0, x = 8; c < cols; c++, x += size)
gadgets[r, c] = new Gadget(canvas) { Color = colors[rg.Next(colors.Length)], Bounds = new Rectangle(x, y, size, size) };
int paintCount = 0, drawCount = 0;
canvas.Paint += (sender, e) =>
{
paintCount++;
for (int r = 0; r < rows; r++)
{
for (int c = 0; c < cols; c++)
{
if (e.ClipRectangle.IntersectsWith(gadgets[r, c].Bounds))
{
gadgets[r, c].Draw(e.Graphics);
drawCount++;
}
}
}
form.Text = $"Paint:{paintCount} Draw:{drawCount} of {(long)paintCount * rows * cols}";
};
var timer = new Timer { Interval = 100 };
timer.Tick += (sender, e) =>
{
gadgets[rg.Next(rows), rg.Next(cols)].Color = colors[rg.Next(colors.Length)];
};
timer.Start();
Application.Run(form);
}
}
}
Not sure how your resizer class works. i think there is problem when you re-size every image every time.
Texture = resizer.ResizeImage(_i, SizeW, SizeH) ;// set texture
i would replace above line like this
Texture = _i;// set texture but do not resize image now
at the same time update the Draw Function of Tile like below.
public void Draw(Graphics _g)
{
//now specify the location and size of the image.
_g.DrawImage(Texture , new Rectangle(this.XPosition, this.YPosition, SizeW, SizeH));
}
hopefully it should improve the performance.
if it flicker then you can use Double Buffer
My friend's GameElements.cs seems to have become corrupted in some way. We're both studying in the same class, and he sent me his project and I can't open the file either. I can't troubleshoot his solution, as he is using XNA and I'm using MonoGame.
Sadly, he does not have any back-ups (this way he'll learn the hard way though) and neither one of us are familiar with neither Visual Studio nor programming at all, as we're just a couple months into the course.
The file is still 12kb, even though I can only select/copy blank spaces. I have no idea if it's possible to restore the code from it, there is obviously data in the file.
This is a link to download the whole solution, though the corrupt file in question is "GameElements.cs". We both would appreciate it greatly if someone was able to recover the code! http://www.filedropper.com/xnabus
Please see below for the code from GameElements.cs. Hope this helps :). You could use any .Net Disassembler to do this. I used ILSpy and decompiled your code from XNA bus.exe file.
Note that, sometimes there could be minor issues with names of classes or methods. So, please go through the code once completely to ensure this.
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using System.Linq;
namespace XNA_bus
{
internal static class GameElements
{
public enum State
{
Menu,
Levels,
Level1,
Level2,
Level3,
Run,
Highscore,
Quit
}
private static Meny meny;
private static Levels levels;
private static Player player;
private static List<Fiender> Fiende;
private static List<GuldMynt> guldMynt;
private static List<Powerup> SuperSkepp;
private static List<Powerup> PenetratingBullets;
private static Texture2D guldMyntSprite;
private static Texture2D SuperskeppSprite;
private static Texture2D PenetratingbulletsSprite;
private static Utskrifter printText;
private static Bakgrund bakgrund;
private static Boss1 boss1;
private static int boss1Liv = 3;
private static int playerLiv = 1;
public static GameElements.State currentState;
public static void Initialize()
{
GameElements.guldMynt = new List<GuldMynt>();
GameElements.SuperSkepp = new List<Powerup>();
GameElements.PenetratingBullets = new List<Powerup>();
}
public static void LoadContent(ContentManager content, GameWindow window)
{
GameElements.player = new Player(content.Load<Texture2D>("Images/player/Player"), 0f, 200f, 2.5f, 4.5f, content.Load<Texture2D>("Images/player/bullet"));
GameElements.bakgrund = new Bakgrund(content.Load<Texture2D>("Images/bakgrund"), window);
GameElements.boss1 = new Boss1(content.Load<Texture2D>("Images/Enemies/Boss1"), 700f, 360f);
GameElements.meny = new Meny(0);
GameElements.meny.AddItem(content.Load<Texture2D>("Images/Meny/Start"), 1, window);
GameElements.meny.AddItem(content.Load<Texture2D>("Images/Meny/Highscore"), 6, window);
GameElements.meny.AddItem(content.Load<Texture2D>("Images/Meny/Avsluta"), 7, window);
GameElements.levels = new Levels(1);
GameElements.levels.AddItem(content.Load<Texture2D>("Images/Meny/Level 1"), 2, window);
GameElements.levels.AddItem(content.Load<Texture2D>("Images/Meny/Level 2"), 3, window);
GameElements.levels.AddItem(content.Load<Texture2D>("Images/Meny/Level 3"), 4, window);
GameElements.Fiende = new List<Fiender>();
Random random = new Random();
Texture2D tmpsprite = content.Load<Texture2D>("Images/Enemies/Predator");
for (int i = 0; i < 5; i++)
{
int rndX = random.Next(window.get_ClientBounds().Width / 2, window.get_ClientBounds().Width - tmpsprite.get_Width());
int rndY = random.Next(0, window.get_ClientBounds().Height - tmpsprite.get_Height());
Predator temp = new Predator(tmpsprite, (float)rndX, (float)rndY);
GameElements.Fiende.Add(temp);
}
tmpsprite = content.Load<Texture2D>("Images/Enemies/mina");
for (int i = 0; i < 5; i++)
{
int rndX = random.Next(window.get_ClientBounds().Width / 2, window.get_ClientBounds().Width - tmpsprite.get_Width());
int rndY = random.Next(0, window.get_ClientBounds().Height - tmpsprite.get_Height());
Mine temp2 = new Mine(tmpsprite, (float)rndX, (float)rndY);
GameElements.Fiende.Add(temp2);
}
GameElements.printText = new Utskrifter(content.Load<SpriteFont>("Font1"));
GameElements.guldMyntSprite = content.Load<Texture2D>("Images/Powerups/SpelMynt");
GameElements.SuperskeppSprite = content.Load<Texture2D>("Images/Powerups/PowerUp");
GameElements.PenetratingbulletsSprite = content.Load<Texture2D>("Images/Powerups/PowerUp2");
}
public static GameElements.State MenyUpdate(GameTime gameTime)
{
return (GameElements.State)GameElements.meny.Update(gameTime);
}
public static void MenyDraw(SpriteBatch spriteBatch)
{
GameElements.bakgrund.Draw(spriteBatch);
GameElements.meny.Draw(spriteBatch);
}
public static GameElements.State RunUpdate(ContentManager content, GameWindow window, GameTime gameTime)
{
GameElements.bakgrund.Update(window);
GameElements.player.Update(window, gameTime);
foreach (Fiender f in GameElements.Fiende.ToList<Fiender>())
{
foreach (Bullet b in GameElements.player.AntSkott.ToList<Bullet>())
{
if (f.CheckCollision(b))
{
f.Liv = false;
GameElements.player.poäng++;
if (!GameElements.player.PenetratingBullets)
{
GameElements.player.AntSkott.Remove(b);
}
else if (GameElements.player.PenetratingBullets)
{
if (gameTime.get_TotalGameTime().TotalSeconds > GameElements.player.PenetratingBulletsTime + 2.0)
{
GameElements.player.PenetratingBullets = false;
}
}
}
}
if (f.Liv)
{
if (f.CheckCollision(GameElements.player))
{
GameElements.playerLiv--;
GameElements.player.Liv = false;
}
f.Update(window);
}
else
{
GameElements.Fiende.Remove(f);
}
if (!f.FKoll)
{
GameElements.Fiende.Remove(f);
GameElements.playerLiv--;
}
}
if (GameElements.boss1.Liv)
{
foreach (Bullet b in GameElements.player.AntSkott.ToList<Bullet>())
{
if (GameElements.boss1.CheckCollision(b))
{
GameElements.player.AntSkott.Remove(b);
GameElements.boss1Liv--;
}
}
GameElements.boss1.Update(window);
}
if (GameElements.boss1Liv == 0)
{
GameElements.boss1.Liv = false;
}
GameElements.State result;
if (!GameElements.boss1.Liv)
{
GameElements.Reset(window, content);
result = GameElements.State.Menu;
}
else
{
Random random = new Random();
int newMynt = random.Next(1, 200);
if (newMynt == 1)
{
int rndX = random.Next(0, window.get_ClientBounds().Width - GameElements.guldMyntSprite.get_Width());
int rndY = random.Next(0, window.get_ClientBounds().Height - GameElements.guldMyntSprite.get_Height());
GameElements.guldMynt.Add(new GuldMynt(GameElements.guldMyntSprite, (float)rndX, (float)rndY));
}
foreach (GuldMynt gc in GameElements.guldMynt.ToList<GuldMynt>())
{
if (gc.Liv)
{
gc.Update(gameTime);
if (gc.CheckCollision(GameElements.player))
{
GameElements.guldMynt.Remove(gc);
GameElements.player.Poäng++;
}
}
else
{
GameElements.guldMynt.Remove(gc);
}
}
Random rnd = new Random();
int newPowerup = rnd.Next(1, 300);
if (newPowerup == 1)
{
int rndX = rnd.Next(0, window.get_ClientBounds().Width - GameElements.SuperskeppSprite.get_Width());
int rndY = rnd.Next(0, window.get_ClientBounds().Height - GameElements.SuperskeppSprite.get_Height());
GameElements.SuperSkepp.Add(new Powerup(GameElements.SuperskeppSprite, (float)rndX, (float)rndY));
}
foreach (Powerup Power in GameElements.SuperSkepp.ToList<Powerup>())
{
if (Power.Liv)
{
Power.Update(gameTime);
if (Power.CheckCollision(GameElements.player))
{
GameElements.SuperSkepp.Remove(Power);
GameElements.player.SuperSkepp = true;
GameElements.player.SuperSkeppTime = gameTime.get_TotalGameTime().TotalSeconds;
}
}
else
{
GameElements.SuperSkepp.Remove(Power);
}
}
Random rnd2 = new Random();
int NewPowerup = rnd2.Next(1, 300);
if (NewPowerup == 1)
{
int rndX = rnd2.Next(0, window.get_ClientBounds().Width - GameElements.PenetratingbulletsSprite.get_Width());
int rndY = rnd2.Next(0, window.get_ClientBounds().Height - GameElements.PenetratingbulletsSprite.get_Height());
GameElements.PenetratingBullets.Add(new Powerup(GameElements.PenetratingbulletsSprite, (float)rndX, (float)rndY));
}
foreach (Powerup P in GameElements.PenetratingBullets.ToList<Powerup>())
{
if (P.Liv)
{
P.Update(gameTime);
if (P.CheckCollision(GameElements.player))
{
GameElements.PenetratingBullets.Remove(P);
GameElements.player.PenetratingBullets = true;
GameElements.player.PenetratingBulletsTime = gameTime.get_TotalGameTime().TotalSeconds;
}
}
else
{
GameElements.PenetratingBullets.Remove(P);
}
}
if (!GameElements.player.Liv || GameElements.playerLiv == 0)
{
GameElements.Reset(window, content);
result = GameElements.State.Menu;
}
else
{
result = GameElements.State.Run;
}
}
return result;
}
public static void RunDraw(SpriteBatch spriteBatch)
{
GameElements.boss1.Draw(spriteBatch);
GameElements.bakgrund.Draw(spriteBatch);
GameElements.player.Draw(spriteBatch);
foreach (Fiender f in GameElements.Fiende)
{
f.Draw(spriteBatch);
}
foreach (GuldMynt gc in GameElements.guldMynt)
{
gc.Draw(spriteBatch);
}
foreach (Powerup Power in GameElements.SuperSkepp)
{
Power.Draw(spriteBatch);
}
foreach (Powerup p in GameElements.PenetratingBullets)
{
p.Draw(spriteBatch);
}
GameElements.printText.Print("Points:" + GameElements.player.poäng, spriteBatch, 0, 0);
GameElements.printText.Print("Boss Liv:" + GameElements.boss1Liv, spriteBatch, 680, 0);
GameElements.printText.Print("Liv:" + GameElements.playerLiv, spriteBatch, 0, 20);
}
public static GameElements.State HighScoreUpdate()
{
GameElements.State result;
if (Keyboard.GetState().IsKeyDown(27))
{
result = GameElements.State.Menu;
}
else
{
result = GameElements.State.Highscore;
}
return result;
}
public static void HighScoreDraw(SpriteBatch spriteBatch)
{
}
private static void Reset(GameWindow window, ContentManager content)
{
GameElements.boss1Liv = 3;
GameElements.playerLiv = 1;
GameElements.boss1.Liv = true;
GameElements.player.Reset(0f, 200f, 2.5f, 4.5f);
GameElements.Fiende.Clear();
Random random = new Random();
Texture2D tmpsprite = content.Load<Texture2D>("Images/Enemies/Predator");
for (int i = 0; i < 5; i++)
{
int rndX = random.Next(window.get_ClientBounds().Width / 2, window.get_ClientBounds().Width - tmpsprite.get_Width());
int rndY = random.Next(0, window.get_ClientBounds().Height - tmpsprite.get_Height());
Predator temp = new Predator(tmpsprite, (float)rndX, (float)rndY);
GameElements.Fiende.Add(temp);
}
tmpsprite = content.Load<Texture2D>("Images/Enemies/mina");
for (int i = 0; i < 5; i++)
{
int rndX = random.Next(window.get_ClientBounds().Width / 2, window.get_ClientBounds().Width - tmpsprite.get_Width());
int rndY = random.Next(0, window.get_ClientBounds().Height - tmpsprite.get_Height());
Mine temp2 = new Mine(tmpsprite, (float)rndX, (float)rndY);
GameElements.Fiende.Add(temp2);
}
}
public static GameElements.State LevelsUpdate(GameTime gameTime)
{
return (GameElements.State)GameElements.levels.Update(gameTime);
}
public static void LevelsDraw(SpriteBatch spritebatch)
{
GameElements.bakgrund.Draw(spritebatch);
GameElements.levels.Draw(spritebatch);
}
}
}
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 Microsoft.Xna.Framework.Storage;
using System.IO;
using System.Xml.Serialization;
namespace ButtonGame
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
MouseState mouse, prevMouse;
/// <param name="gameTime">Provides a snapshot of timing values.</param>
public IAsyncResult result;
public Object stateobj;
public bool GameSaveRequested = false;
public GamePadState currentState;
public class GameImages
{
//Image Diminsions and Graphic
public Texture2D texture;
//Images position on the Viewport
public Vector2 position = new Vector2(0, 0);
}//GameImages
GameImages button;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.PreferredBackBufferWidth = 800;
graphics.PreferredBackBufferHeight = 600;
graphics.PreferMultiSampling = false;
graphics.IsFullScreen = false;
}//Game1()
protected override void Initialize()
{
button = new GameImages();
base.Initialize();
}//Initialize
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
//Gives the button the graphic "button.PNG" from resources
button.texture = Content.Load<Texture2D>("Button");
//Sets the drawing point of the button to the middle of the screen
button.position = new Vector2(300, 400);
}
protected override void Update(GameTime gameTime)
{
//Gets current position and condition of the mouse
mouse = Mouse.GetState();
//Makes the cursor visible on the screen of the game
this.IsMouseVisible = true;
//If the User has released the Left mouse button and previously had it pressed, (Left Clicked)
if (mouse.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Released && prevMouse.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
{
//Check if the mouse was within the bounds of GameImage button
if (CheckForClick(button))
{
//Remove the button from view
button.position = new Vector2(5000, 5000);
}
if (mouse.Y > 600)
{
button.texture = Content.Load<Texture2D>("Catch - Red");
}
}
if (mouse.X < 50)
{
button.position.X += 3;
}
else if (mouse.X > 500)
{
button.position.X -= 3;
}
//If the User has released the Right mouse button and previously had it pressed, (Right Clicked)
else if ((mouse.RightButton == Microsoft.Xna.Framework.Input.ButtonState.Released && prevMouse.RightButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed))
{
//Bring Back the button
//button.position = new Vector2(300,400);
InitiateSave();
}
else if ((mouse.MiddleButton == Microsoft.Xna.Framework.Input.ButtonState.Released && prevMouse.MiddleButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed))
{
InitiateLoad();
}
//Store the current mouse position and conditon into a orevious state to prepare for new input
prevMouse = mouse;
base.Update(gameTime);
}//Update
/// <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)
{
spriteBatch.Begin();
//Background Color
GraphicsDevice.Clear(Color.CornflowerBlue);
//if button is not off the screen
if (button.position != new Vector2(5000, 5000))
{
//Draw the button
DrawImage(button);
}
spriteBatch.End();
base.Draw(gameTime);
}//Draw
public void DrawImage(GameImages image)
{
spriteBatch.Draw(image.texture, image.position, Color.White);
}//DrawImage
public bool CheckForClick(GameImages rectangle)
{
if (mouse.Y < rectangle.position.Y + rectangle.texture.Height &&
mouse.Y > rectangle.position.Y &&
mouse.X > rectangle.position.X &&
mouse.X < rectangle.position.X + rectangle.texture.Width)
return true;
else
return false;
}//CheckForClick
StorageDevice device;
string containerName="MyGamesStorage";
string filename = "mysave.sav";
public struct SaveGame
{
public Vector2 buttonPosition;
public Texture2D newbuttonTexture;
}//Save Game
private void InitiateSave()
{
device = null;
StorageDevice.BeginShowSelector(PlayerIndex.One, this.SaveToDevice, null);
}
void SaveToDevice(IAsyncResult result)
{
device = StorageDevice.EndShowSelector(result);
if (device != null && device.IsConnected)
{
SaveGame SaveData = new SaveGame()
{
buttonPosition = button.position,
newbuttonTexture = button.texture,
};
IAsyncResult r = device.BeginOpenContainer(containerName, null, null);
result.AsyncWaitHandle.WaitOne();
StorageContainer container = device.EndOpenContainer(r);
if (container.FileExists(filename))
container.DeleteFile(filename);
Stream stream = container.CreateFile(filename);
XmlSerializer serializer = new XmlSerializer(typeof(SaveGame));
serializer.Serialize(stream, SaveData);
stream.Close();
container.Dispose();
result.AsyncWaitHandle.Close();
}
}
private void InitiateLoad()
{
device = null;
StorageDevice.BeginShowSelector(PlayerIndex.One, this.LoadFromDevice, null);
}
void LoadFromDevice(IAsyncResult result)
{
device = StorageDevice.EndShowSelector(result);
IAsyncResult r = device.BeginOpenContainer(containerName, null, null);
result.AsyncWaitHandle.WaitOne();
StorageContainer container = device.EndOpenContainer(r);
result.AsyncWaitHandle.Close();
if (container.FileExists(filename))
{
Stream stream = container.OpenFile(filename, FileMode.Open);
XmlSerializer serializer = new XmlSerializer(typeof(SaveGame));
SaveGame SaveData = (SaveGame)serializer.Deserialize(stream);
stream.Close();
container.Dispose();
//Update the game based on the save game file
button.position = SaveData.buttonPosition;
button.texture = SaveData.newbuttonTexture;
}
}
}
}
I've simplified and reproduced my problem in a smaller program so its easier to share.
When I run the program and Right click to save, then move the object's location a bit so I can see a change and then middle click to load the game, I get the error.
What I did to reproduce the error:
Run the program
Right Click - This saved the game
Left click with the mouse past the bottom of the screen - This changes the button's image to "Catch - Red"
Position mouse to the left of the screen so that the button moves
Middle Click so that the game loads the previously saved data, the button should be centered with it's first image "button"
This is where I get the error message
ObjectdispsoedException was unhandled Cannot access a disposed object. Object name: 'Texture2D'.
on the spriteBatch.End(); line.
Admittedly I did just copy and past the save and load classes from the internet, I don't know how each step fully works.
Goal for the code: I want to be able to save the data, such as location, assigned content, arrays etc. So that it can be loaded again later.
First, you shouldn't be loading content in update. It should be done in "loadcontent", hence the name... You should load the 2 textures in load content and then swap them in update.
Second, the problem is where you set texture2D again in the load function. Because what content.load() does is loads the texture onto the graphics card. But if you reset it then the reference will change. This relates back to my first point. You should have already loaded the content when content.load is called. So you should separate the texture2d and the game objects.
For example (wont compile, but you get the idea):
class MyGameObject
{
public int textureIndex = 0;
public Vector2 position = new Vector2(0, 0);
}
class Game
{
Texture2D[] textures;
MyGameObject poop;
void loadContent()
{
textures = new Texture2D[2];
textures[0] = Content.Load<Texture2D>("a texture");
textures[1] = Content.Load<Texture2D>("different texture");
poop = new MyGameObject();
poop.textureIndex = 0;
}
void update()
{
if (mouse.Y > 600)
{
poop.textureIndex = 1;
}
}
void draw()
{
spriteBatch.draw(textures[poop.textureIndex], poop.position);
}
....other stuff....
}
Greetings
I genereated a terrain with this equation:
H(x,y) = (abs(sin(x * y)) + abs(sin(0,2 * x) + sin(0,4 * y)) + abs(cos(0,12 * x) + cos(0,47 * y))) * e^(0.005*(x+y))
Now, this gives me a mix of featuresize, and a nice slope. This works fine, when I plot it using scilab.
I tried to import this in a c# application.
The terrain is created in this code:
using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX;
using System.Collections.Generic;
namespace Kamera_eins
{
public partial class Terrain : Form
{
public double[,] DTM;
string response ;
public Terrain()
{
InitializeComponent();
response = "";
DTM = new double[2048/4,2048/4];
}
public void BoxTheSky()
{
}
public void BoxTheLand()
{
mesh();
surf();
}
public void begin()
{
}
public void mesh()
{
response = "";
int i = new int();
int j = new int();
i = 0;
j = 0;
for (i=0;i<2048/4 ;i++ ) {
for (j=0;j<2048/4 ;j++ ) {
DTM[i,j] = Math.Abs (Math.Sin (j*i)) + Math.Abs(Math.Sin(0.2*i) * Math.Sin(0.4*j) ) + Math.Abs(Math.Cos(0.12* i) * Math.Cos(0.47*j));
DTM[i,j] = Math.Pow(Math.E, (0.012* (i + j)));
}
}
response = "DTM mesh ready";
}
public void surf()
{
}
}
}
This is kept in a file called terrain.cs, and i make this a winform, because i plan to add a simple textbox, where i can later make some sort of realtime log of the process.
Now, there is another file, and in that file, intend to display this terrain. this second file goes as follows:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Data;
using System.IO;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.DirectInput;
namespace Kamera_eins
{
public class viewport : Form
{
public Microsoft.DirectX.Direct3D.Device device = null;
public PresentParameters presentparameter = new PresentParameters();
public bool device_exists;
public bool show;
public int HEIGHT;
public int WIDTH;
public string paintDesc;
private float angle ;
private CustomVertex.PositionColored[] vertices;
public double[,] heightData;
private int[] indices;
private IndexBuffer ib;
private VertexBuffer vb;
private Microsoft.DirectX.DirectInput.Device keyb;
//public
public viewport()
{
this.ClientSize = new System.Drawing.Size(600, 600);
this.Text = "Terrain viewport";
WIDTH = 2048 / 4;
HEIGHT = 2048 / 4;
heightData = new double[HEIGHT,WIDTH];
keyb = new Microsoft.DirectX.DirectInput.Device(SystemGuid.Keyboard);
keyb.SetCooperativeLevel(this, CooperativeLevelFlags.Background | CooperativeLevelFlags.NonExclusive);
keyb.Acquire();
presentparameter.Windowed = true;
presentparameter.SwapEffect = SwapEffect.Discard;
presentparameter.AutoDepthStencilFormat = DepthFormat.D16;
presentparameter.EnableAutoDepthStencil = true;
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
try {
device = new Microsoft.DirectX.Direct3D.Device(0, Microsoft.DirectX.Direct3D.DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentparameter);
device.DeviceLost += new EventHandler(this.InvalidateDeviceObjects);
device.DeviceReset += new EventHandler(this.RestoreDeviceObjects);
device.Disposing += new EventHandler(this.DeleteDeviceObjects);
device.DeviceResizing += new CancelEventHandler(this.EnvironmentResizing);
device_exists = true;
} catch (Exception DirectException) {
device_exists = false;
}
}
private void setcamera()
{
device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, this.Width / this.Height, 1f, 50f);
device.Transform.View = Matrix.LookAtLH (new Vector3(0, 0, 100), new Vector3(0, 0, 0) , new Vector3(0,0,1) );
device.RenderState.Lighting = false;
device.RenderState.FillMode = FillMode.WireFrame;
device.RenderState.CullMode = Cull.None;
}
public void declareVertex()
{
vb = new VertexBuffer(typeof(CustomVertex.PositionColored), HEIGHT*WIDTH, device, Usage.Dynamic | Usage.WriteOnly, CustomVertex.PositionColored.Format, Pool.Default);
vertices = new CustomVertex.PositionColored[HEIGHT*WIDTH];
for (int x=0;x< WIDTH;x++) {
for (int y=0; y< HEIGHT;y++) {
vertices[x + y * WIDTH].Position = new Vector3(x, y, (float)heightData[x,y]);
int r = Convert.ToInt32(205 * heightData[x,y] / 200 );
if(r>254)
r = 254;
vertices[x + y * WIDTH].Color = Color.FromArgb( r , 120 , 120).ToArgb();
}
}
vb.SetData(vertices, 0, LockFlags.None);
}
public void declareIndex()
{
ib = new IndexBuffer(typeof(int), (WIDTH-1)*(HEIGHT-1)*6, device, Usage.WriteOnly, Pool.Default);
indices = new int[(WIDTH-1)*(HEIGHT-1)*6];
for (int x=0;x< WIDTH-1;x++) {
for (int y=0; y< HEIGHT-1;y++) {
indices[(x+y*(WIDTH-1))*6] = (x+1)+(y+1)*WIDTH;
indices[(x+y*(WIDTH-1))*6+1] = (x+1)+y*WIDTH;
indices[(x+y*(WIDTH-1))*6+2] = x+y*WIDTH;
indices[(x+y*(WIDTH-1))*6+3] = (x+1)+(y+1)*WIDTH;
indices[(x+y*(WIDTH-1))*6+4] = x+y*WIDTH;
indices[(x+y*(WIDTH-1))*6+5] = x+(y+1)*WIDTH;
}
}
ib.SetData(indices, 0, LockFlags.None);
}
protected override void Dispose (bool disposing)
{
base.Dispose(disposing);
MessageBox.Show("");
}
protected virtual void InvalidateDeviceObjects(object sender, EventArgs e)
{
}
protected virtual void RestoreDeviceObjects(object sender, EventArgs e)
{
}
protected virtual void DeleteDeviceObjects(object sender, EventArgs e)
{
}
protected virtual void EnvironmentResizing(object sender, CancelEventArgs e)
{
}
public void run()
{
while(this.Created)
{
render();
setcamera();
// optional: loading the height using functional call:
// loadheight();
Application.DoEvents();
}
}
public void render()
{
if (device != null)
{
device.Clear(ClearFlags.Target, Color.Black, 1.0f, 0);
device.BeginScene();
//display terrain
device.VertexFormat = CustomVertex.PositionColored.Format;
device.SetStreamSource(0, vb, 0);
device.Indices = ib;
device.Transform.World = Matrix.Translation(-HEIGHT/2, -WIDTH/2, 0)*Matrix.RotationZ(angle) ;
device.DrawIndexedPrimitives(PrimitiveType.TriangleFan, 0, 0, WIDTH*HEIGHT, 0, indices.Length/3);
//turn off lights now
device.EndScene();
device.Present();
this.Invalidate();
readkeyboard();
}
}
void readkeyboard()
{
KeyboardState keys = keyb.GetCurrentKeyboardState();
if (keys[Key.Delete])
{
angle+=0.03f;
}
if (keys[Key.Next])
{
angle-=0.03f;
}
}
public void openport()
{
}
protected override void OnPaint(PaintEventArgs e)
{
render();
setcamera();
}
}
}
Now, yet a third file calls the world creation and display:
void MainFormLoad(object sender, EventArgs e)
{
world = new World();
world.setterrain();
}
the surf and box-somthing functions do not yet do anything.
All what i get now, is just a black window (the device.clear(... ) part) - i tried to adjust the camera .. no success
please help, i want to show the terrain in the window ....