How to generate infinitly enemies in XNA? [closed] - c#

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I was developing a game using XNA frame work and here is my code
I just want to generate infinite number of enemies
here is my code please help
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;
namespace fight_in_the_sky
{
/// <summary>
/// This is the main type for your game
/// </summary>
///
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spritebatch;
Texture2D anim, background1, background2, enemy;
Rectangle rect0, rect2, rectdst, srcrect, rect3, rect4, srcrect2, enemy_rect;
float elapsed;
float delay = 40f;
int frames = 0;
Random random = new Random();
public Vector2 velocity;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.PreferredBackBufferWidth = 800;
graphics.PreferredBackBufferHeight = 600;
IsMouseVisible = true;
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
rectdst = new Rectangle(0, 250, 115, 69);
rect3 = new Rectangle(0,0,1280,720);
rect4 = new Rectangle(1280, 0, 1280, 720);
enemy_rect = new Rectangle(random.Next(800-94,800-47),random.Next(600-122,600-61),376/8,61);
velocity.X = 3f;
velocity.Y = 3f;
base.Initialize();
}
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spritebatch = new SpriteBatch(GraphicsDevice);
background1= Content.Load<Texture2D>("starfield006");
background2= Content.Load<Texture2D>("starfield005");
anim=Content.Load<Texture2D>("shipAnimation");
enemy =Content.Load<Texture2D>("mineAnimation");
rect0 = new Rectangle(0, 0, 800, 600);
rect2 = new Rectangle(0, 250,200, 100);
// TODO: use this.Content to load your game content here
}
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
// if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
// this.Exit();
// TODO: Add your update logic here
elapsed += (float)gameTime.ElapsedGameTime.Milliseconds;
if (Keyboard.GetState().IsKeyDown(Keys.Left))
{
rectdst.X -= 12;
if (rectdst.X < 0) { rectdst.X = 0; }
}
if (Keyboard.GetState().IsKeyDown(Keys.Right))
{
rectdst.X += 12;
if (rectdst.X > 700) { rectdst.X = 700; }
}
if (Keyboard.GetState().IsKeyDown(Keys.Up))
{
rectdst.Y -= 12;
if (rectdst.Y < 0) { rectdst.Y = 0; }
}
if (Keyboard.GetState().IsKeyDown(Keys.Down))
{ rectdst.Y += 10; if (rectdst.Y > 550) { rectdst.Y = 550; } }
base.Update(gameTime);
if (elapsed >= delay)
{
if (frames >= 7)
{ frames = 0; }
else { frames++; }
elapsed = 0;
}
srcrect = new Rectangle(115 * frames, 0, 115, 69);
srcrect2 = new Rectangle(47*frames,0,47,61);
if (rect3.X + background1.Width <= 0)
rect3.X = rect4.X + background2.Width;
if (rect4.X + background2.Width <= 0)
rect4.X = rect3.X + background1.Width;
rect3.X -= 5;
rect4.X -= 5;
enemy_rect.X +=(int) velocity.X;
enemy_rect.Y += (int)velocity.Y;
if (enemy_rect.Y >= 600 - 61 || enemy_rect.Y <= 0) velocity.Y = -velocity.Y;
if (enemy_rect.X >= 800 - 47) velocity.X = -velocity.X;
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
// TODO: Add your drawing code here
spritebatch.Begin();
spritebatch.Draw(background1,rect3, Color.Azure);
spritebatch.Draw(background2,rect4, Color.Azure);
spritebatch.Draw(anim, rectdst, srcrect, Color.White);
spritebatch.Draw(enemy, enemy_rect, srcrect2, Color.White);
spritebatch.End();
base.Draw(gameTime);
}
}
}
and here is a shot of my current output
http://imgur.com/7y43S7O

Infinite is unpractical to build into a game, because sooner or later you would either run out of RAM or your screen would be too full to call it a game. Anyway, I can give you a basic idea to work with.
If you want your enemy count to keep increasing you can use a list and add an enemy every time you want one to appear
List<Enemy> enemies = new List<Enemy>;
In Update:
if(spawnTimer > spawnInterval && enemies.Count()<enemyLimit){
enemies.add(new Enemy([rectangle of spawn location and image size]);
spawnTimer = 0;
}
for(int i=0; i<enemies.Count();i++){
if(enemies[i].defeated){
enemies.Remove(enemies[i]);
}
spawnTimer+=gameTime.ElapsedGameTime.TotalSeconds;
in Draw:
for(int i=0; i<enemies.Count();i++){
spritebatch.Draw(enemy, enemies[i].Rect, srcrect2, Color.White);
}
class Enemy{
public Rectangle Rect{get;set;}
public bool defeated{get;set;}
public int Health{get;set;}
public Enemy(Rectangle rect){
Rect = rect;
Health = 100;
defeated = false;
}
}

Related

C# bouncing cubes game, remove cubes from 100px of the center

I am making a small "game" in Monogame with C# of 2000 blocks that bounce around the screen. I need to make the cubes disappear if they are within a circle 100px of the center of the screen. The 2 classes i have are (Game1.cs) which is the game itself, and then (Block.cs) which is the code for the blocks bouncing around the screen, here is the code for both:
Game1.cs:
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
namespace Inlämning2
{
public class Game1 : Game
{
private GraphicsDeviceManager _graphics;
private SpriteBatch _spriteBatch;
Texture2D pixelTexture;
List<Block> blocks = new List<Block>();
public Game1()
{
_graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
IsMouseVisible = true;
}
protected override void Initialize()
{
Random rnd = new Random();
// TODO: Add your initialization logic here
for (int i = 0; i < 1000; i++)
{
var block = new Block();
block.X = rnd.Next(0, 600);
block.Y = rnd.Next(0, 400);
block.Color = new Color(rnd.Next(256), rnd.Next(256), rnd.Next(256));
blocks.Add(block);
}
base.Initialize();
}
protected override void LoadContent()
{
// TODO: use this.Content to load your game content here
_spriteBatch = new SpriteBatch(GraphicsDevice);
pixelTexture = Content.Load<Texture2D>("pixel");
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
foreach (Block block in blocks)
{
block.Update();
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
_spriteBatch.Begin();
foreach (Block block in blocks)
{
block.Draw(_spriteBatch, pixelTexture);
}
_spriteBatch.End();
base.Draw(gameTime);
}
}
}
---------------------------------------------Block.cs:--------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace Inlämning2
{
class Block
{
public int X { get; set; } = 100;
public int Y { get; set; } = 100;
public Color Color { get; set; } = Color.Red;
public int speed1 = 1;
public int speed2 = -1;
public void Draw(SpriteBatch spriteBatch, Texture2D texture)
{
spriteBatch.Draw(texture, new Rectangle(X, Y, 30, 30), Color);
}
public void Update()
{
if (X< 0) speed2 += 1;
if (X > 770) speed2 += -1;
if (Y > 450) speed1 += -1;
if (Y< 0) speed1 += 1;
X += speed2;
Y += speed1;
if (speed1 > 1) speed1 = 1;
if (speed2 > 1) speed2 = 1;
}
}
}
Calculate the center of the screen as a Vector2 called Center.
//pseudo C# code:
if (Center - X,Y).LengthSquared() < 100 * 100) //fix this line
... then remove block Blocks.Remove(this), not possible during an enumeration, find another way.
If the question is referring to Manhattan Distance the formula: if((Math.Abs(Center.X -X) + Math.Abs(Center.Y -Y))< 100)
would apply.

How to debug where an unexpected null is coming from in my class?

In my Boss class, it says that my List "bulletlist" is null and give me a run time error but I see no errors can someone tell me what I am doing wrong? The games runs fine if I don't update my boss class. I put in my main class, player class, and bullet class, in as well.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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;
namespace Space_Shooter
{
public class Boss
{
public Texture2D texture, bulletTexture , healthBarTexture;
public Vector2 position;
public float randomPositionX, randomPositionY , bulletDamage, shipDamage , health , MaxBullets;
public int speed, bulletSpeed , bulletDelayTime, bulletDelayTimeReset;
public bool isVisible;
public Rectangle boundingBox , bossHealthBar;
public List<Bullet> bulletList;
Random random = new Random();
Player p = new Player();
public Boss(Texture2D newTexture, Vector2 newPosition, Texture2D newBulletTexture)
{
texture = newTexture;
position = newPosition;
bulletTexture = newBulletTexture;
bulletList = new List<Bullet>();
bulletSpeed = 25;
bulletDamage = 25;
shipDamage = p.health / 2;
health = 2000;
bulletDelayTime = 30;
bulletDelayTimeReset = 30;
MaxBullets = 30;
isVisible = true;
}
public Boss()
{
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(texture, position, Color.White);
spriteBatch.Draw(healthBarTexture, bossHealthBar, Color.White);
foreach (Bullet b in bulletList)
{
b.Draw(spriteBatch);
}
}
public void loadContent(ContentManager content)
{
texture = content.Load<Texture2D>("Ship4");
bulletTexture = content.Load<Texture2D>("EnemyBullet");
healthBarTexture = content.Load <Texture2D> ("healthbar");
}
public void update(GameTime gameTime)
{
updateBullets();
Shoot();
checkBossCollison();
// Making bosses health bar
bossHealthBar = new Rectangle((int)position.X, (int)position.Y + 30, (int)health, 25);
// Creating collision box for boss
boundingBox = new Rectangle((int)position.X, (int)position.Y, (int)texture.Width, (int)texture.Height);
randomPositionX = random.Next(50, 750);
randomPositionY = random.Next(50, 400);
// setting boss movement
if (position.Y > randomPositionY)
position.Y -= speed;
if (position.Y < randomPositionY)
position.Y += speed;
if (position.X > randomPositionX)
position.X -= speed;
if (position.X < randomPositionX)
position.X += speed;
}
public void updateBullets()
{
// for each bullet in the bulletList: update the movement and if the bullet hits the bottom of the screen, remove it from the list
foreach (Bullet b in bulletList)
{
//make a Bounding box for every bullet in the bulletList
b.boundingBox = new Rectangle((int)b.position.X, (int)b.position.Y, b.texture.Width, b.texture.Height);
// set movement for the bullets
// if a bullet hits the bottom of the screen, then make visable false
if (b.position.Y >= 850)
b.isVisible = false;
// go through the bulletList and see if any of the bullets are not visible, if they are not then remove that bullet from the bulletList
for (int i = 0; i < bulletList.Count; i++)
{
if (!bulletList[i].isVisible)
{
bulletList.RemoveAt(i);
i--;
}
}
}
}
public void checkBossCollison()
{
// if boss ship comes in bcontact with player ship player is damaged
if (boundingBox.Intersects(p.boundingBox))
p.health -= shipDamage;
// if player bullets hit boss then boss is damaged and player bullets go invisible
for(int i = 0; i < p.bulletList.Count; i++)
{
if (boundingBox.Intersects(p.bulletList[i].boundingBox))
{
health -= p.bulletDamage;
p.bulletList[i].isVisible = false;
if (health == 0)
isVisible = false;
}
}
// if boss shoots player player is damaged and boss bullets go invisible
for(int i = 0; i < bulletList.Count; i++)
{
if (p.boundingBox.Intersects(bulletList[i].boundingBox))
{
p.health -= bulletDamage;
bulletList[i].isVisible = false;
}
}
}
public void Shoot()
{
// shoot only if our bullet delay resets
if (bulletDelayTime >= 0)
bulletDelayTime--;
// If bulletDelay is at 0, create a new bullet at enemy position, make it visible on the screen, then add that bullet to bulletList
if (bulletDelayTime <= 0)
{
// create new bullet and center it front and center of enemy ship
Bullet newBullet = new Bullet(bulletTexture);
newBullet.position = new Vector2(position.X + texture.Width / 2 - newBullet.texture.Width / 2, position.Y + 30);
newBullet.isVisible = true;
if (bulletList.Count() < MaxBullets)
bulletList.Add(newBullet);
}
// Reset bullet delay
if (bulletDelayTime == 0)
bulletDelayTime = bulletDelayTimeReset;
}
}
}
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;
namespace Space_Shooter
{
// Main
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
// variabls
SpriteBatch spriteBatch;
Random random = new Random();
Random randomNumberOfAsteroids = new Random();
int maxNumberOfAsteroids;
int numbersOfInvisibleEnemies;
// Lists
List<Asteroid> asteroidList = new List<Asteroid>();
List<Enemy> enemyList = new List<Enemy>();
// making player and starfield objects
Player P = new Player();
StarField starfield = new StarField();
Enemy E = new Enemy();
Boss boss = new Boss();
// Construtor
public Game1()
{
graphics = new GraphicsDeviceManager(this);
// setting full scren to off and setting screen measurments
graphics.IsFullScreen = false;
graphics.PreferredBackBufferWidth = 800;
graphics.PreferredBackBufferHeight = 850;
maxNumberOfAsteroids = 5; // Set the max number of asteroids that will be on the screen at one time ( randomly 0 to Max number)
numbersOfInvisibleEnemies = 0;
// Setting Title of screen
this.Window.Title = "Star Voyage";
Content.RootDirectory = "Content";
}
// Initialize
protected override void Initialize()
{
base.Initialize();
}
// Load content
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
// Call Load content function from Player.cs
P.LoadContent(Content);
starfield.LoadContent(Content);
boss.loadContent(Content);
}
// unload content
protected override void UnloadContent()
{
}
// update game screen
protected override void Update(GameTime gameTime)
{
// updating enemies and checking collision of thier ships to player ship
foreach (Enemy e in enemyList)
{
if (e.boundingBox.Intersects(P.boundingBox))
{
P.health -= e.enemyShipDamage;
e.isVisible = false;
}
// check enemy bullet collision with player ship
for (int i = 0; i < e.bulletList.Count; i++)
{
if (P.boundingBox.Intersects(e.bulletList[i].boundingBox))
{
P.health -= e.enemyBulletDamage;
e.bulletList[i].isVisible = false;
}
}
// check player bullet collision with enemy ships
for (int i = 0; i < P.bulletList.Count; i++)
{
if (e.boundingBox.Intersects(P.bulletList[i].boundingBox))
{
// when bullet hits enemy ship they disapear
P.bulletList[i].isVisible = false;
e.health -= P.bulletDamage;
if (e.health == 0)
e.isVisible = false;
}
}
e.Update(gameTime);
}
// for each asteroid in the asteroid list call the update function from Asteroid.cs
foreach (Asteroid a in asteroidList)
{
//Check to see if any of the arteroids are colliding with player ship
if (a.boundingBox.Intersects(P.boundingBox))
{
P.health -= a.asteroidDamage; // taking 20 off of player health bar each time the play shit is hit by an asteroid
a.isVisible = false;
}
// going through bullet list to see if any bullets come in contact with asteroids if they do set both the bullet and the asteroid to not visible
for (int i = 0; i < P.bulletList.Count; i++)
{
if (a.boundingBox.Intersects(P.bulletList[i].boundingBox))
{
a.isVisible = false;
P.bulletList.ElementAt(i).isVisible = false;
}
}
a.Update(gameTime);
}
loadAsteroids();
loadEnemyShips();
// Call fucntion Update from Player,cs
P.Update(gameTime);
// Call function update from StarField.cs
starfield.Update(gameTime);
boss.update(gameTime);
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
base.Update(gameTime);
}
// Draw to game screen
protected override void Draw(GameTime gameTime)
{
spriteBatch.Begin();
starfield.Draw(spriteBatch);
foreach (Asteroid a in asteroidList)
{
a.Draw(spriteBatch);
}
foreach (Enemy e in enemyList)
{
e.Draw(spriteBatch);
}
// Backgound color
GraphicsDevice.Clear(Color.CornflowerBlue);
// Call Draw fuction from Player.cs
P.Draw(spriteBatch);
// boss.Draw(spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}
// Load Asteroids function
public void loadAsteroids()
{
// creating random variabls for X and Y positions of asteroids
int random_x = random.Next(0, 750), random_y = random.Next(-600, -50);
// if the number of Asteroids on the screen is less than the variable (numberOfAsteroids), create more untill it is not
if (asteroidList.Count() < randomNumberOfAsteroids.Next(0, maxNumberOfAsteroids))
{
asteroidList.Add(new Asteroid(Content.Load<Texture2D>("asteroid"), new Vector2(random_x, random_y)));
}
// if any of the asteroids from the list are destroyed (not visible) then remove them from the list
for (int i = 0; i < asteroidList.Count; i++)
{
if (!asteroidList[i].isVisible)
{
asteroidList.RemoveAt(i);
i--;
}
}
}
public void loadEnemyShips()
{
// creating random variabls for X and Y positions of asteroids
int random_x = random.Next(0, 750), random_y = random.Next(-600, -50);
// if the number of enemies on the screen is less than the variable (numberOfEnemies), create more untill it is not
if (enemyList.Count() < 3 && numbersOfInvisibleEnemies <= 9)
{
enemyList.Add(new Enemy(Content.Load<Texture2D>("enemyship"), new Vector2(random_x, random_y), Content.Load<Texture2D>("EnemyBullet")));
}
// keeping count of the number of destroied enemies
for (int i = 0; i < enemyList.Count; i++)
{
if (!enemyList[i].isVisible)
numbersOfInvisibleEnemies += 1;
// if any of the enemies from the list are destroyed (not visible) or if they go passed the bottom of the screen, then remove them from the list
if (!enemyList[i].isVisible || enemyList[i].position.Y >= 840)
{
enemyList.RemoveAt(i);
--i;
}
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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;
namespace Space_Shooter
{
// main
public class Player
{
// Variables
public Texture2D texture , bulletTexture , healthTexture;
public Vector2 position , healthBarPosition;
public int speed;
public float health , bulletDamage , bulletDelay , bulletDelayReset;
double bulletCount;
// Lists
public List<Bullet> bulletList;
// Collision variables
public bool isColliding;
public Rectangle boundingBox , healthRectangle;
// Constructor
public Player()
{
bulletList = new List<Bullet>();
bulletDelay = 1; // for faster fire rate reduce number
bulletDelayReset = 5; // bullet delay reset has to be the same number as bullet delay
bulletCount = 1000; // amount of bullets alowed on the screen at a time
texture = null;
health = 200;
bulletDamage = 3;
healthBarPosition = new Vector2(50, 50);
position = new Vector2 (300, 300) ;
speed = 10;
isColliding = false;
}
// Load content
public void LoadContent(ContentManager Content)
{
texture = Content.Load<Texture2D>("player01");
bulletTexture = Content.Load<Texture2D>("playerbullet");
healthTexture = Content.Load<Texture2D>("healthbar");
}
// Draw
public void Draw(SpriteBatch spritebatch)
{
spritebatch.Draw(texture, position, Color.White);
spritebatch.Draw(healthTexture, healthRectangle, Color.White);
// For each Bullet b (bullet) in our bullet list, draw the bullet
foreach (Bullet b in bulletList)
{
b.Draw(spritebatch);
}
}
// Update
public void Update(GameTime gametime)
{
// Checking for keyboard input every frame
KeyboardState keystate = Keyboard.GetState();
// setting collision box for player ship
boundingBox = new Rectangle((int)position.X, (int)position.Y, texture.Width, texture.Height);
//set rectangle for healthbar (where to print on the screen and the height and width (25) is height (health is width
healthRectangle = new Rectangle((int) healthBarPosition.X, (int) healthBarPosition.Y, (int)health, 25);
if (keystate.IsKeyDown(Keys.Space))
{
shoot();
}
updateBullets();
// ship controls
if (keystate.IsKeyDown(Keys.W))
position.Y = position.Y - speed;
if (keystate.IsKeyDown(Keys.S))
position.Y = position.Y + speed;
if (keystate.IsKeyDown(Keys.A))
position.X = position.X - speed;
if (keystate.IsKeyDown(Keys.D))
position.X = position.X + speed;
// Keep ship in screen bounds
if (position.X <= 0)
position.X = 0;
if (position.X >= 800 - texture.Width)
position.X = 800 - texture.Width;
if (position.Y <= 0)
position.Y = 0;
if (position.Y >= 850 - texture.Height)
position.Y = 850 - texture.Height;
}
// Shoot Function, used to set the starting position of the players bullet
public void shoot()
{
// Shoot only if the bullet delay resets
if (bulletDelay >= 0)
bulletDelay--;
// If bulletDelay is at 0, create a new bullet at player position, make it visible on the scrren, then add that bullet to bulletList
if (bulletDelay <= 0)
{
Bullet newBullet1 = new Bullet(bulletTexture);
newBullet1.position = new Vector2(position.X - newBullet1.texture.Width / 2, position.Y + 30);
newBullet1.isVisible = true;
Bullet newBullet2 = new Bullet(bulletTexture);
newBullet2.position = new Vector2(position.X + 64 - newBullet2.texture.Width / 2, position.Y + 30);
newBullet2.isVisible = true;
// control the amount of bullets on the screen by increasing number
if (bulletList.Count() < bulletCount)
bulletList.Add(newBullet1);
bulletList.Add(newBullet2);
}
// Reset bullet dleay
if (bulletDelay == 0)
bulletDelay = bulletDelayReset;
}
public void updateBullets()
{
// for each bullet in the bulletList: update the movement and if the bullet hits the top of the screen, remove it from the list
foreach (Bullet b in bulletList)
{
// set movement for the bullets
b.position.Y = b.position.Y - b.speed;
//make a Bounding box for every bullet in the bullet list
b.boundingBox = new Rectangle((int)b.position.X, (int)b.position.Y, b.texture.Width, b.texture.Height);
// if a bullet hits the top of the screen, then make visable false
if (b.position.Y <= 0)
b.isVisible = false;
}
// go through the bulletList and see if any of the bullets are not visible, if they are not then remove that bullet from the bulletList
for (int i = 0; i < bulletList.Count; i++)
{
if (!bulletList[i].isVisible)
{
bulletList.RemoveAt(i);
i--;
}
}
}
}
}
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;
namespace Space_Shooter
{
public class Bullet
{
public Rectangle boundingBox;
public Texture2D texture;
public Vector2 position , origin;
public float speed;
public bool isVisible;
public Bullet(Texture2D newTexture)
{
speed = 25;
texture = newTexture;
isVisible = false;
}
public void Draw(SpriteBatch spritebatch)
{
spritebatch.Draw(texture, position, Color.White);
}
}
}
You initialize the list in the constructor:
public Boss(Texture2D newTexture, Vector2 newPosition, Texture2D newBulletTexture)
But, you don't call this constructor. You call Boss boss = new Boss();
Thus the constructor which initializes the list is not called.
You should initialize the list in all constructors:
public Boss()
{
bulletList = new List<Bullet>();
}
Better is too make the default constructor set all the default values, and if you need to set other values in another constructor, is to call the default constructor from the "second" constructor using : this():
public Boss()
{
bulletList = new List<Bullet>();
bulletSpeed = 25;
bulletDamage = 25;
shipDamage = p.health / 2;
health = 2000;
bulletDelayTime = 30;
bulletDelayTimeReset = 30;
MaxBullets = 30;
isVisible = true;
}
public Boss(Texture2D newTexture, Vector2 newPosition, Texture2D newBulletTexture)
: this() //Call default constructor
{
texture = newTexture;
position = newPosition;
bulletTexture = newBulletTexture;
}

Drawing Multiple Sprites with Different Properties in XNA 4.0

I'm writing a bit of code where I animate a hundred copies of the same sprite onto the screen by creating a sprite class. I want the sprites, an animation of four-ring interlocking rings spinning within each other, to be drawn at a certain height, drop down on the screen, and bounce like a ball, with each bounce being progressively less until it they stop completely. I have managed to get this part done; however, I can't seem to find a way to randomize the acceleration and animation speed of each different sprite. Can someone provide some suggestions to my code?
Game 1.cs
namespace lab_6
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Sprite rings;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.PreferredBackBufferHeight = 600;
graphics.PreferredBackBufferWidth = 800;
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
Texture2D rings_texture = Content.Load<Texture2D>("Images/threerings");
//animation
Point frameSize = new Point(75, 75);
Point currentFrame = new Point(0, 0);
Point sheetSize = new Point(6, 8);
int millisecondsPerFrame = 50;
rings = new Sprite(rings_texture, ringsPos,
frameSize, 0, currentFrame, sheetSize, ringsSpeed, millisecondsPerFrame);
}
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <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();
if (Keyboard.GetState().IsKeyDown(Keys.Escape))
this.Exit();
// TODO: Add your update logic here
rings.Update(gameTime, Window.ClientBounds);
base.Update(gameTime);
}
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
// TODO: Add your drawing code here
spriteBatch.Begin();
rings.Draw(gameTime, spriteBatch);
spriteBatch.End();
}
}
}
Sprite.cs
namespace lab_6
{
public class Sprite
{
//basics
protected Texture2D rings;
protected Vector2 ringsPos = new Vector2(0,0);
protected Color tint = Color.White;
protected Vector2 ringsSpeed = new Vector2(0,0);
protected Vector2 ringsAccel = new Vector2(0, 1);
//animation
protected Point frameSize = new Point(75,75);
protected Point currentFrame = new Point(0, 0);
protected Point sheetSize = new Point(6,8);
//animation timing
protected int timeSinceLastFrame = 0;
protected int millisecondsPerFrame = 50;
const int defaultMillisecondsPerFrame = 16;
//bounding box offset
protected int collisionOffset;
Random r = new Random(DateTime.Now.Millisecond);
public Sprite(Texture2D rings, Vector2 ringsPos, Point frameSize,
int collisionOffset, Point currentFrame, Point sheetSize, Vector2 ringsSpeed,
int millisecondsPerFrame)
{
this.rings = rings;
this.ringsPos = ringsPos;
this.frameSize = frameSize;
this.collisionOffset = collisionOffset;
this.currentFrame = currentFrame;
this.sheetSize = sheetSize;
this.ringsSpeed = ringsSpeed;
this.millisecondsPerFrame = millisecondsPerFrame;
}
public virtual void Update(GameTime gameTime, Rectangle clientBounds)
{
int maxY = (600 - frameSize.Y );
ringsAccel.Y += (byte)r.Next((1 / 10), 1);
ringsSpeed.Y += ringsAccel.Y;
ringsPos.Y += ringsSpeed.Y;
if (ringsPos.Y > maxY)
{
ringsSpeed *= -0.8f;
ringsPos.Y = maxY;
}
//Update animation frame
millisecondsPerFrame = 50;
millisecondsPerFrame *= ((byte)r.Next(1, 10));
timeSinceLastFrame += gameTime.ElapsedGameTime.Milliseconds;
if (timeSinceLastFrame > millisecondsPerFrame)
{
timeSinceLastFrame = 0;
++currentFrame.X;
if (currentFrame.X >= sheetSize.X)
{
currentFrame.X = 0;
++currentFrame.Y;
if (currentFrame.Y >= sheetSize.Y)
currentFrame.Y = 0;
}
}
}
public virtual void Draw(GameTime gameTime, SpriteBatch spriteBatch)
{
for(int i = 0; i < 100; )
{
Vector2 newPos = ringsPos + new Vector2((10 * i), (1 * (byte)r.Next((1/10), 1)));
spriteBatch.Draw(rings, newPos,
new Rectangle(currentFrame.X * frameSize.X,
currentFrame.Y * frameSize.Y,
frameSize.X, frameSize.Y),
tint, 0, Vector2.Zero, 1f, SpriteEffects.None, 0);
i++;
r = new Random(DateTime.Now.Second);
}
}
}
}
Move the constructor for ringSpeed and ringAccel to the constructor and randomize them there.

While Enemy attacking he cant die

I'm making a platform game in Monogame where I have enemies that make the attack frame when it should but if i try to kill it, it get stuck in the frame and cant die.
Here is my Game1 code:
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.Graphics;
using Microsoft.Xna.Framework.Input;
namespace TreasureHunt
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
int enemyLives = 2;
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
SoundEffect aj;
SoundEffect collect;
Texture2D coinCount;
int screenWidth = 1024;
int screenHeight = 768;
//int enemyLives = 2;
//Vector2 temp = new Vector2 (1000, 600);
Pirate player;
List<EnemyPirate> argh = new List<EnemyPirate>();
List<Coin> coin = new List<Coin>();
bool firstPirateArmy = true;
Level map;
Vector2 dist;
Vector2 coindist;
Background backGround;
int collectedCoins;
SpriteFont inGameFont;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
graphics.PreferredBackBufferWidth = screenWidth;
graphics.PreferredBackBufferHeight = screenHeight;
graphics.IsFullScreen = false;
Window.Title = "TreasureHunt";
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()
{
map = new Level (screenWidth, screenHeight);
map.LoadMap (Content, 1);
backGround = new Background(screenWidth, (int)(Level.GetWorldSize().X * Level.GetTileSize()), 1, Content);
player = new Pirate(screenWidth, screenHeight, Content, graphics.GraphicsDevice);
argh.Add(new EnemyPirate(screenWidth, screenHeight, Content, new Vector2(400, 400), enemyLives));
argh.Add(new EnemyPirate(screenWidth, screenHeight, Content, new Vector2(1600, 420), enemyLives));
argh.Add(new EnemyPirate(screenWidth, screenHeight, Content, new Vector2(3800, 600), enemyLives));
coin.Add (new Coin (screenWidth, screenHeight, Content, new Vector2 (505, 278)));
coin.Add (new Coin (screenWidth, screenHeight, Content, new Vector2 (1100, 25)));
coin.Add (new Coin (screenWidth, screenHeight, Content, new Vector2 (890, 660)));
coin.Add (new Coin (screenWidth, screenHeight, Content, new Vector2 (1720, 660)));
coin.Add (new Coin (screenWidth, screenHeight, Content, new Vector2 (2348, 410)));
coin.Add (new Coin (screenWidth, screenHeight, Content, new Vector2 (2850, 150)));
coin.Add (new Coin (screenWidth, screenHeight, Content, new Vector2 (2950, 660)));
base.Initialize();
}
private void ResetPirates()
{
if(firstPirateArmy)
{
argh.Add(new EnemyPirate(screenWidth, screenHeight, Content, new Vector2(1000, 500), enemyLives));
argh.Add(new EnemyPirate(screenWidth, screenHeight, Content, new Vector2(1500, 50), enemyLives));
argh.Add(new EnemyPirate(screenWidth, screenHeight, Content, new Vector2(3700, 200), enemyLives));
firstPirateArmy = false;
}
else
{
argh.Add(new EnemyPirate(screenWidth, screenHeight, Content, new Vector2(400, 400), enemyLives));
argh.Add(new EnemyPirate(screenWidth, screenHeight, Content, new Vector2(1600, 420), enemyLives));
argh.Add(new EnemyPirate(screenWidth, screenHeight, Content, new Vector2(3800, 600), enemyLives));
firstPirateArmy = true;
}
}
/// <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);
inGameFont = Content.Load<SpriteFont>("inGameFont");
aj = Content.Load<SoundEffect> ("AjLjud");
collect = Content.Load<SoundEffect> ("Collecting1");
coinCount = Content.Load<Texture2D> ("Coin");
}
/// <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();
player.Update (gameTime);
for (int i = 0; i < coin.Count (); i++) {
coin [i].Update (gameTime);
coindist = (coin [i].GetPosition () - player.GetPosition ());
if (coindist.Length () < 60) {
collect.Play ();
coin.RemoveAt (i);
collectedCoins++;
}
}
for (int i = 0; i < argh.Count (); i++) {
dist = (argh [i].GetPosition () - player.GetPosition ());
if (dist.Length () < 100) {
argh [i].Attack ();//.currentState = EnemyPirate.figureState.hitting;
player.playerLives--;
}
}
for (int i = 0; i < argh.Count(); i++)
{
argh[i].Update(gameTime);
if (player.HasHitEnemy(argh[i].GetBoundingBox()))
{
argh [i].enemyLives--;
aj.Play ();
argh [i].hurt = true;
if (argh [i].enemyLives <= 0) {
argh [i].currentState = EnemyPirate.figureState.predie;
argh [i].EnemyIsDead ();
//if(argh[i].dead)
//argh.RemoveAt (i);
}
if (argh.Count() == 0)
ResetPirates();
}
if (argh [i].currentState == EnemyPirate.figureState.died)
argh.RemoveAt (i);
}
map.UpdateCamera(player.GetPosition());
backGround.Update ();
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);
spriteBatch.Begin (SpriteSortMode.Deferred,
null,
SamplerState.PointClamp,
null,
null);
backGround.Draw (spriteBatch);
map.Draw (spriteBatch);
foreach (EnemyPirate c in argh)
c.Draw (spriteBatch);
foreach (Coin c in coin)
c.Draw (spriteBatch);
player.Draw (spriteBatch);
//spriteBatch.DrawString(inGameFont, "speed.Y:" + player.position.Y, new Vector2(20, 20), Color.White);
spriteBatch.DrawString(inGameFont, "R = Reset", new Vector2(20, 20), Color.White);
spriteBatch.DrawString(inGameFont, "dist: "+dist.Length()+" "+player.playerLives, new Vector2(20, 40), Color.White);
spriteBatch.DrawString(inGameFont, ": " + collectedCoins, new Vector2(55, 70), Color.White);
spriteBatch.Draw (coinCount, new Vector2 (20, 60), Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
and here is my enemycode:
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
namespace TreasureHunt
{
public class EnemyPirate : PlatformerFigure
{
public int enemyLives = 2;
int animWalk = 0;
int animHit = 6;
int animPreDie = 9;
// int animDie = 10;
public figureState currentState;
public bool dead;
public bool hurt;
public const float _delay = 3; // seconds
public float _remainingDelay = _delay;
public enum figureState // Alla olika stadier figuren kan befinna sig i
{
standing,
walking,
jumping,
predie,
die,
died,
hitting
}
public EnemyPirate (int screenWidth, int screenHeight, ContentManager contMan, Vector2 position, int Lives)
{
this.screenWidth = screenWidth;
this.screenHeight = screenHeight;
LoadMedia(contMan);
enemyLives = Lives;
animSequence = new int[]{ 1, 2, 3, 4, 5, 0, 7, 8, 0, 10, 11, 11 };
SetBoundingBox (new Rectangle (10, 15, 63, 81));
Reset ();
this.position = position;
}
public void Reset()
{
Facing = AnimatedObject.direction.left;
SetFrame(animWalk);
currentState = figureState.standing;
maxSpeed = new Vector2(1f, 6);
//position = new Vector2(1600, 400); // Behövs inte när man skickar in en position till konstruktorn.
speed = Vector2.Zero;
slipperyK = 1;
acc = Vector2.Zero; // Från början står figuren still.
walkAcc = 1f;
primaryColor = Color.White;
alpha = 1;
}
private void LoadMedia(ContentManager content)
{
gfx = content.Load<Texture2D>("EnemyPirate2");
AnimationSettings(96, 96, 110, direction.right, 12);
}
public override bool Update(GameTime gameTime)
{
var timer = (float) gameTime.ElapsedGameTime.TotalSeconds;
Think();
Move(gameTime);
UpdateAnimation(gameTime);
GroundCollision();
if (currentState == figureState.hitting && currentFrame == 0)
currentState = figureState.standing;
// else if (enemyLives <= 0)
// currentState = figureState.predie;
if (currentState == figureState.predie) {
_remainingDelay -= timer;
if (_remainingDelay < 2) {
alpha -= 0.04f;
if (alpha < 0)
alpha = 0;
}
}
if (_remainingDelay <= 0)
currentState = figureState.died;
return true;
}
private void Think()
{
if (Facing == direction.left)
{
acc.X = -walkAcc;
if (WallCollision(new Vector2(-10,0)) || !GroundAhead())
{
Facing = direction.right;
acc.X = walkAcc;
}
}
else
{
acc.X = walkAcc;
if (WallCollision(new Vector2(10,0)) || !GroundAhead())
{
Facing = direction.left;
acc.X = -walkAcc;
}
}
}
private bool GroundAhead()
{
Vector2 ahead = position + pos_feet; // Vart finns figurens fötter?
if (Facing == direction.left)
ahead += new Vector2(-10, 0); // Tittar lite till vänster om figuren
else
ahead += new Vector2(10, 0); // Tittar lite till höger om figuren
int tile = Level.GetTile(ahead);
if (tile > 44 && tile < 77 || tile > 84 && tile < 104)
return true;
return false;
}
public void EnemyIsDead ()
{
if (currentState == figureState.predie)
SetFrame (animPreDie);
acc = Vector2.Zero;
walkAcc = 0;
dead = true;
}
public void Hurted()
{
if (hurt) {
var pos = position.X;
while(position.X < pos-5){
position = new Vector2 (position.X, 0);
}
}
}
public void Attack()
{
if (currentState != figureState.hitting) {
SetFrame (animHit);
currentState = figureState.hitting;
}
}
}
}
That's way too much code. You've got no Asserts or Exceptions. Make your code super brittle, so that if something wrong happens it will stop and alert you to fix it.
eg. Inside Argh.Attack(), Assert that currentState is not already dead.

Player collision on a singe image map

The problem that I am having is wrapping my brain around how I could use a single png called Test Map.png:
This has a black border around the screen and smaller stepping blocks for the player to test the collision. I have the gravity working by using a player class and the main class Game1.cs to draw and update the game. I use this ball:
This is my sprite that I move around the screen.
Here is the player.cs:
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;
namespace Gravity_Test_V2
{
class Player
{
public Texture2D Texture;
public Vector2 Velocity;
public Vector2 Position;
public float ground;
private float Speed;
private Rectangle screenBound;
public bool isJumping; //are we jumping or not
public bool goingUp; //if going up or not
public float initialVelocity; //initial velocity
private float jumpU; //How high the player can jump
private float g; //gravity
public float t; //time
private KeyboardState prevKB;
public Player(Texture2D Texture, Vector2 Position, float Speed, Rectangle screenBound)
{
this.Texture = Texture;
this.Position = Position;
ground = Position.Y;
this.Speed = Speed;
this.screenBound = screenBound;
Velocity = Vector2.Zero;
isJumping = goingUp = true;
jumpU = 2.5f;
g = -9.8f;
t = 0;
}
public void Update(GameTime gameTime)
{
Position.X += (Velocity.X * Speed);
//Set the Y position to be subtracted so that the upward movement would be done by decreasing the Y value
Position.Y -= (Velocity.Y * Speed);
goingUp = (Velocity.Y > 0);
// TODO: Add your update logic here
if (isJumping == true)
{
//motion equation using velocity: v = u + at
Velocity.Y = (float)(initialVelocity + (g * t));
//Increase the timer
t += (float)gameTime.ElapsedGameTime.TotalSeconds;
}
if (isJumping == true && Position.Y > screenBound.Height - Texture.Height)
{
Position.Y = ground = screenBound.Height - Texture.Height;
Velocity.Y = 0;
isJumping = false;
t = 0;
}
if (Position.X < 0)
{
//if Texture touches left side of the screen, set the position to zero and the velocity to zero.
Position.X = 0;
Velocity.X = 0;
}
else if (Position.X + Texture.Width > screenBound.Width)
{
//if Texture touches left side of the screen, set the position to zero and the velocity to zero.
Position.X = screenBound.Width - Texture.Width;
Velocity.X = 0;
}
if (Position.Y < 0)
{
//if the Texture touches the top of the screen, reset the timer and set the initial velocity to zero.
Position.Y = 0;
t = 0;
initialVelocity = 0;
}
}
public void Input(KeyboardState keyState)
{
if (keyState.IsKeyDown(Keys.Space) && (isJumping == false || Position.Y == ground))
{
isJumping = true;
initialVelocity = jumpU;
}
if (keyState.IsKeyDown(Keys.Left) && !keyState.IsKeyDown(Keys.Right))
{
if (Velocity.X > -1.0f)
{
Velocity.X -= (1.0f / 10);
}
else
{
Velocity.X = -1.0f;
}
}
else if (!keyState.IsKeyDown(Keys.Left) && keyState.IsKeyDown(Keys.Right))
{
if (Velocity.X < 1.0f)
{
Velocity.X += (1.0f / 10);
}
else
{
Velocity.X = 1.0f;
}
}
else
{
if (Velocity.X > 0.05 || Velocity.X < -0.05)
Velocity.X *= 0.70f;
else
Velocity.X = 0;
}
prevKB = keyState;
}
public void Fall()
{
t = 0;
initialVelocity = 0;
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(Texture, new Rectangle((int)Position.X, (int)Position.Y, Texture.Width, Texture.Height), Color.White);
}
}
}
Is there some simple way to make it so the player can collide with the Test Map.png while its inside the Test Map's texture?
EDIT: 1/21/2014 9 AM 'ish'
Level One:
EDIT: 1/21/2014 10:27
I have used a pixle based system to test to see if the player colides with an object but I try to sepreate the object from the play into classes and it will stop working. I mixed both my movment and collision projects together to try and make it work. I took player.cs (witch I have not changed) and added the pixel based collision into the Game1.cs I need to know how to make the player, witch is being controlled by the player.cs class, be seen by the Game1.cs class and used while being called upon by the player.cs class.
Note* I have also changed it so that the game would be using the falling triangles supplied by the pixel based system. I will add the test image when I am able to make this work.
At the moment The player can move and jump but is not reconsidered as colliding.
EDIT: 1/21/2014 10:34
I use 2 projects:
Collision:
http://xbox.create.msdn.com/en-US/education/catalog/tutorial/collision_2d_perpixel
Movment System:
http://gamepopper.co.uk/academic-projects/2012-2/jumping-platformer-example/
I have mixed them up and used pices of them to try and make my own platform.
Game1.cs:
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;
namespace Collision_Test
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
KeyboardState prevKB;
Player player;
SpriteFont font;
Texture2D personTexture;
Texture2D blockTexture;
// The color data for the images; used for per pixel collision
Color[] personTextureData;
Color[] blockTextureData;
Vector2 personPosition;
const int PersonMoveSpeed = 5;
public static int screenWidth = 800;
public static int screenHeight = 500;
// Blocks
List<Vector2> blockPositions = new List<Vector2>();
float BlockSpawnProbability = 0.01f;
const int BlockFallSpeed = 1;
Random random = new Random();
// For when a collision is detected
bool personHit = false;
// The sub-rectangle of the drawable area which should be visible on all TVs
Rectangle safeBounds;
// Percentage of the screen on every side is the safe area
const float SafeAreaPortion = 0.05f;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
this.graphics.PreferredBackBufferWidth = screenWidth;
this.graphics.PreferredBackBufferHeight = screenHeight;
this.graphics.ApplyChanges();
}
protected override void Initialize()
{
base.Initialize();
// Calculate safe bounds based on current resolution
Viewport viewport = graphics.GraphicsDevice.Viewport;
safeBounds = new Rectangle(
(int)(viewport.Width * SafeAreaPortion),
(int)(viewport.Height * SafeAreaPortion),
(int)(viewport.Width * (1 - 2 * SafeAreaPortion)),
(int)(viewport.Height * (1 - 2 * SafeAreaPortion)));
// Start the player in the center along the bottom of the screen
personPosition.X = (safeBounds.Width - personTexture.Width) / 2;
personPosition.Y = safeBounds.Height - personTexture.Height;
}
/// <summary>
/// Load your graphics content.
/// </summary>
protected override void LoadContent()
{
blockTexture = Content.Load<Texture2D>("Block");
personTexture = Content.Load<Texture2D>("Person");
font = Content.Load<SpriteFont>("Font");
player = new Player(personTexture, Vector2.Zero, 6.0f, new Rectangle(0, 0,
this.graphics.PreferredBackBufferWidth,
this.graphics.PreferredBackBufferHeight));
// Extract collision data
blockTextureData =
new Color[blockTexture.Width * blockTexture.Height];
blockTexture.GetData(blockTextureData);
personTextureData =
new Color[personTexture.Width * personTexture.Height];
personTexture.GetData(personTextureData);
// Create a sprite batch to draw those textures
spriteBatch = new SpriteBatch(graphics.GraphicsDevice);
}
void HandleInput(KeyboardState keyState)
{
player.Input(keyState);
if (prevKB.IsKeyUp(Keys.F) && keyState.IsKeyDown(Keys.F))
{
this.graphics.ToggleFullScreen();
this.graphics.ApplyChanges();
}
}
protected override void Update(GameTime gameTime)
{
// Get input
KeyboardState keyboard = Keyboard.GetState();
GamePadState gamePad = GamePad.GetState(PlayerIndex.One);
HandleInput(Keyboard.GetState());
player.Update(gameTime);
prevKB = Keyboard.GetState();
// Allows the game to exit
if (gamePad.Buttons.Back == ButtonState.Pressed ||
keyboard.IsKeyDown(Keys.Escape))
{
this.Exit();
}
// Spawn new falling blocks
if (random.NextDouble() < BlockSpawnProbability)
{
float x = (float)random.NextDouble() *
(Window.ClientBounds.Width - blockTexture.Width);
blockPositions.Add(new Vector2(x, -blockTexture.Height));
}
// Get the bounding rectangle of the person
Rectangle personRectangle =
new Rectangle((int)personPosition.X, (int)personPosition.Y,
personTexture.Width, personTexture.Height);
// Update each block
personHit = false;
for (int i = 0; i < blockPositions.Count; i++)
{
// Animate this block falling
blockPositions[i] =
new Vector2(blockPositions[i].X,
blockPositions[i].Y + BlockFallSpeed);
// Get the bounding rectangle of this block
Rectangle blockRectangle =
new Rectangle((int)blockPositions[i].X, (int)blockPositions[i].Y,
blockTexture.Width, blockTexture.Height);
// Check collision with person
if (IntersectPixels(personRectangle, personTextureData,
blockRectangle, blockTextureData))
{
personHit = true;
}
// Remove this block if it have fallen off the screen
if (blockPositions[i].Y > Window.ClientBounds.Height)
{
blockPositions.RemoveAt(i);
// When removing a block, the next block will have the same index
// as the current block. Decrement i to prevent skipping a block.
i--;
}
}
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 device = graphics.GraphicsDevice;
// Change the background to red when the person was hit by a block
if (personHit)
{
device.Clear(Color.Red);
}
else
{
device.Clear(Color.CornflowerBlue);
}
spriteBatch.Begin();
player.Draw(spriteBatch);
// Draw blocks
foreach (Vector2 blockPosition in blockPositions)
spriteBatch.Draw(blockTexture, blockPosition, Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
/// <summary>
/// Determines if there is overlap of the non-transparent pixels
/// between two sprites.
/// </summary>
/// <param name="rectangleA">Bounding rectangle of the first sprite</param>
/// <param name="dataA">Pixel data of the first sprite</param>
/// <param name="rectangleB">Bouding rectangle of the second sprite</param>
/// <param name="dataB">Pixel data of the second sprite</param>
/// <returns>True if non-transparent pixels overlap; false otherwise</returns>
static bool IntersectPixels(Rectangle rectangleA, Color[] dataA,
Rectangle rectangleB, Color[] dataB)
{
// Find the bounds of the rectangle intersection
int top = Math.Max(rectangleA.Top, rectangleB.Top);
int bottom = Math.Min(rectangleA.Bottom, rectangleB.Bottom);
int left = Math.Max(rectangleA.Left, rectangleB.Left);
int right = Math.Min(rectangleA.Right, rectangleB.Right);
// Check every point within the intersection bounds
for (int y = top; y < bottom; y++)
{
for (int x = left; x < right; x++)
{
// Get the color of both pixels at this point
Color colorA = dataA[(x - rectangleA.Left) +
(y - rectangleA.Top) * rectangleA.Width];
Color colorB = dataB[(x - rectangleB.Left) +
(y - rectangleB.Top) * rectangleB.Width];
// If both pixels are not completely transparent,
if (colorA.A != 0 && colorB.A != 0)
{
// then an intersection has been found
return true;
}
}
}
// No intersection found
return false;
}
}
}
Provided the background of the texture is transparent, you could use Per-Pixel Collision detection.
Essentially it checks the pixels rather than a rectangular box to determine if a collision has occurred. Given your "player" is a ball, it's probably a good idea to use this anyway.
Considering that your map is only black & White, you could process it before starting the game and obtain coords of every Rectangle of black areas, and then use it to use simple collision detection by just checking intersection between the ball bounding box and rectangles.
For example, in pseudocode:
You have a list:
List<Rectangle> rects = new List<Rectangle>();
void LoadMap()
{
Texture2D map = Content.Load<Texture2D>(#"TexturePath");
//Get a 1D array with image's pixels
Color[] map_pixels = new Color[map.Width * map.Height];
map.GetData(map_pixels);
//Convert it in a 2D array
Color[,] map_pixels_2D = new Color[map.Width, map.Height];
for (int x = 0; x < map.Width; x++)
for (int y = 0; y < map.Height; y++)
map_pixels_2D[x, y] = map_pixels[x + y * map.Width];
//**NOTE THAT**: From here it is just an example, probably not working good,
//I wrote it just to share the idea
//Here goes the code to trace rectangles in the map
Rectangle r = Rectangle.Empty;
bool NWvertex_done = false, NEvertex_done = false, SWvertex_done = false;
for (int x = 0; x < map.Width; x++)
{
if (!SWvertex_done)
{
if (map_pixels_2D[x, y+1] == Color.White); //last bottom vertex
{
r.Height = r.Y + y;
SWvertex_done = true;
rects.Add(r);
NWvertex_done = false;
NEvertex_done = false;
r = Rectangle.Empty;
}
}
for (int y = 0; y < map.Height; y++)
{
if (map_pixels_2D[x, y] != Color.White
{
if (!NWvertex_done)
{
SWvertex_done = false;
r.X = x;
r.Y = y;
NWvertex_done = true;
}
else if(!NEvertex_done)
{
if (map_pixels_2D[x, y+1] == Color.White); //last right vertex
{
r.Width = r.X + x;
NEvertex_done = true;
}
}
}
}
}
}
public override void Update(GameTime gametime)
{
//maybe other things
//
foreach (Rectangle rect in rects)
{
//Better with Distance of ball-center and rect
if (ballRect.Intersect(rect))
{
//there is a collision!
//Do something
}
break;
}
//maybe other things
//
}

Categories

Resources