I'm new to C# and Monogame, and I'm trying to create an effect of a 'psychic' ability, the user will press a key and a circular aura blast will emit from their position. I'm just trying to get the actual blast working before setting up the positions and all that, but my problem is when trying to get all the particles to move out from the origin of a circle to the outside.
I've never worked with circles yet and only with Rectangles so my knowledge of this is very basic. You'll probably recognise the code from a youtube channel and that's because I've been trying to learn from wherever I can, most of the time that leads me to youtube since a video demonstration works best but I digress.
This is my code for the particle generator so far.
namespace Particles
{
class ParticleGenerator
{
Texture2D texture;
float spawnWidth;
float density;
List<Particles> particles = new List<Particles>();
float timer;
public ParticleGenerator(Texture2D newTexture, float newSpawnWidth, float newDensity)
{
texture = newTexture;
spawnWidth = newSpawnWidth;
density = newDensity;
}
public void createParticle(GraphicsDevice graphics)
{
particles.Add(new Particles(texture, new Vector2(graphics.Viewport.Width / 2 , graphics.Viewport.Height /2), new Vector2(5, 1)));
}
public void Update(GameTime gameTime, GraphicsDevice graphics)
{
timer += (float)gameTime.ElapsedGameTime.TotalSeconds;
while (timer > 0)
{
timer -= 1f / density;
createParticle(graphics);
}
for (int i = 0; i < particles.Count; i++)
{
particles[i].Update();
if (particles[i].Position.Y > graphics.Viewport.Height)
{
particles.RemoveAt(i);
i--;
}
}
}
public void Draw(SpriteBatch spriteBatch)
{
foreach (Particles particle in particles)
{
particle.Draw(spriteBatch);
}
}
}
}
Many thanks for any help.
Related
I know this question is very specific to those familiar with both tiled and monogame, so I'll try to be a thorough as possible. I've been working on this issue for 15+ hours and am desperate.
I'm trying to draw sprites to the screen using Tiled's object layer. I've created a new object layer, drew some rectangles to it, and added a custom property which I reference in my LoadContent method.
Here is my LoadContent Method:
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
mymap = Content.Load<TiledMap>("Misc/newmap");
enemyShip = Content.Load<Texture2D>("Enemies/enemyship");
//TiledMapObject[] islands = mymap.GetLayer<TiledMapObjectLayer>("Islands").Objects;
ship_sprite = Content.Load<Texture2D>("character/wooden_ship");
Texture2D texture = Content.Load<Texture2D>("character/anima2");
animatedSprite = new AnimatedSprite(texture, 1, 2);
font = Content.Load<SpriteFont>("Misc/londrinasolid");
Song song = Content.Load<Song>("Music/Chad_Crouch_-_Stellars_Jay");
MediaPlayer.Volume = 0.7F;
MediaPlayer.Play(song);
TiledMapObject[] littleBoats = mymap.GetLayer<TiledMapObjectLayer>("SmallBoats").Objects;
foreach (var en in littleBoats)
{
string type;
en.Properties.TryGetValue("type", out type);
if (type == "smallboat")
{
Enemy.enemies.Add(new SmallBoat(en.Position));
}
}
// TODO: use this.Content to load your game content here
}
I've created a TiledMapObject Array which takes the items from the tiledmap object layer. It also checks the custom property name. If it it's "type", which you can see labeled in the bottom lefthand corner of the tiledmap picture, it takes that object and adds it to the array at the position on the tiledmap (at least it's supposed to).
In the draw method, I create a temporary Texture2D variable which references the aforementioned enemy list (which is now filled with two elements from the tiled map). If type Smallboat, it then draws the sprite I want to draw, which it does, just at the wrong position. Here is the relevant draw method:
foreach (Enemy en in Enemy.enemies)
{
Texture2D spritetoDraw;
int rad;
if (en.GetType() == typeof(SmallBoat))
{
rad = 16;
spritetoDraw = enemyShip;
}
else
{
rad = 30;
spritetoDraw = ship_sprite;
}
spriteBatch.Draw(spritetoDraw, new Vector2(en.Position.X - rad, en.Position.Y - rad), Color.White);
}
And here is the starting position of the enemy boat once I run, it's slightly offset from the origin 0,0 because in the draw method I subtract the radius:
Here is my Enemy class, with the SmallBoat child class at the bottom. I've created a new list which should contain the objects from the tiled layer once they are added in the LoadContent method in my main file. I've checked that the objects are being added by using Enemy.Remove(), and they are, so I know that at least the program recognizes the objects in the tiled file.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace my_first_game
{
class Enemy
{
private Vector2 position;
protected int radius;
float circle = MathHelper.Pi * 2;
public float rotationAngle;
protected int health;
public static List<Enemy> enemies = new List<Enemy>();
public int Radius { get { return radius; } }
public Vector2 Position { get { return position; }}
public int Health { get { return health; } set { value = health; } }
public Enemy(Vector2 newpos)
{
newpos = position;
}
public void Update(GameTime gametime, Vector2 playerPos)
{
rotationAngle = circle % 2;
double dt = gametime.ElapsedGameTime.TotalSeconds;
Vector2 direction = new Vector2((float)Math.Cos(rotationAngle), (float)Math.Sin(rotationAngle));
Vector2 movedir = Position - playerPos;
movedir.Normalize();
position -= movedir;
}
}
class SmallBoat : Enemy
{
public SmallBoat(Vector2 newpos) : base(newpos)
{
//radius = 50;
}
}
}
What I've tried:
1). commented out all update methods and ran, nothing changes except the ship's don't move.
2). Drawn new rectangles, erased old ones, deleted and created object layers.
3). if I remove a rectangle from the object layer, there are less boats drawn to the screen once the game is running. Therefore I know that the enemies are being drawn to the screen, just not at the right position.
4). Changed the coordinates to a hardcoded fixed number in the draw method instead of en.position.X and en.position.Y. This changes the starting position to the desired location, but it's hardcoded and doesn't solve the problem.
5). Rearranged elements in the loadcontent method and draw method, to no avail.
It seems that the list is being properly referenced and that the issue is that for some reason the coordinates on the tiled map aren't transfering over. Much of my code is based off of a Udemy Monogame tutorial, and the loadcontent method and draw method are basically the same.
Any and all help is warmly welcomed. Please let me know if there's any other information I can provide.
Edit: Here is the entire draw method.
protected override void Draw(GameTime gameTime)
{
controller.controller_update(gameTime);
spriteBatch.Begin();
if (controller.ingame == false)
{
spriteBatch.DrawString(font, "Welcome to Thallasaphobia. \n press Enter to Begin", new Vector2(100, 100), Color.White);
}
spriteBatch.End();
if (controller.ingame == true)
{
GraphicsDevice.Clear(Color.Black);
mapRenderer.Draw(mymap, cam.GetViewMatrix());
spriteBatch.Begin(transformMatrix: cam.GetViewMatrix());
animatedSprite.Draw(spriteBatch, new Vector2(480, 350));
//create a new rectangle around the ship_sprite
Rectangle ship_rectangle = new Rectangle(0, 0, ship_sprite.Width, ship_sprite.Height);
Vector2 origin = new Vector2(ship_sprite.Width / 2, ship_sprite.Height + 15);
foreach (Enemy en in Enemy.enemies)
{
Texture2D spritetoDraw;
int rad;
if (en.GetType() == typeof(SmallBoat))
{
rad = 16;
spritetoDraw = enemyShip;
}
else
{
rad = 30;
spritetoDraw = ship_sprite;
}
spriteBatch.Draw(spritetoDraw, new Vector2(en.Position.X - rad, en.Position.Y - rad), Color.White);
}
spriteBatch.Draw(ship_sprite, ship.Position, ship_rectangle, Color.White, ship.rotationAngle + MathHelper.Pi/2, origin, 1.0f, SpriteEffects.None, 1);
}
spriteBatch.End();
base.Draw(gameTime);
}
Although I don't really have a means of testing this, I believe the problem is in your constructor. You currently have this code:
public Enemy(Vector2 newpos)
{
newpos = position;
}
You should actually have:
public Enemy(Vector2 newpos)
{
position = newpos;
}
Since "position" is the property of the Enemy class, THAT is the value we want updated, not newpos, which is just a parameter. So that would explain why your enemy is starting at the origin, because its position is never being initially set.
So I'm pretty new to computer programming, but I know the basics of C#.
I'm working on a Monogame project and was making an update method for my sprites. Since my sprites are terraria based (I mean that every sprite is a different bodypart) I made a children list. In that list I put all the body sprites and I attach the list to a parent (center sprite of the player).
This is my basic sprite update method: (not only for player)
public virtual void Update(GameTime gameTime, Rectangle clientBounds)
{
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;
}
}
}
}
This is my player sprite update method in another class:
public override void Update(GameTime gameTime, Rectangle clientBounds)
{
position += direction;
// If sprite moves off screen
if (position.X < 0)
{
position.X = 0;
}
if (position.Y < 0)
{
position.Y = 0;
}
if (position.X > clientBounds.Width - frameSize.X)
{
position.X = clientBounds.Width - frameSize.X;
}
if (position.Y > clientBounds.Height - frameSize.Y)
{
position.Y = clientBounds.Height - frameSize.Y;
}
// Continue base update method
base.Update(gameTime, clientBounds);
}
And this is the draw method, wich works just fine:
public override void Draw(GameTime gameTime)
{
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, DepthStencilState.Default, RasterizerState.CullCounterClockwise);
player.Draw(gameTime, spriteBatch);
player.children.ForEach(c => c.Draw(gameTime, spriteBatch));
spriteBatch.End();
base.Draw(gameTime);
}
But the update method is lagging:
public override void Update(GameTime gameTime)
{
player.children.Add(playerDeux);
float millisecondsRunning = 30;
float millisecondsWalking = millisecondsRunning * 2f;
if (player.running == true)
{
player.millisecondsPerFrame = millisecondsRunning;
}
else if (player.running == false)
{
player.millisecondsPerFrame = 65;
playerDeux.millisecondsPerFrame = 30;
}
if (player.walking == false)
{
player.textureImage = Game.Content.Load<Texture2D>(#"Images/" + s1[1]);
}
player.Update(gameTime, Game.Window.ClientBounds);
player.children.ForEach(c => c.Update(gameTime, Game.Window.ClientBounds));
base.Update(gameTime);
}
So when I call the draw method on all the children it works just fine, but when I call the Update method on the children it lags very much and the program even stops working.
Is there a better way to do this?
EDIT: also note that this class is not done yet, it's just a test where I draw 2 sprites and update (animation plays) them.
+ The s1[1] in player.textureImage = Game.Content.Load(#"Images/" + s1[1]); is just a string name in an array.
There are some oddities with your code, but I think the main culprit is the player.children.Add(playerDeux). The way it is right now, you're adding playerDeux to the children list every single update, and then updating playerDeux once for every time Update has already run. It looks like you want to move this line of code to your Initialize or LoadContent methods.
Also, you should probably load the texture only once in the LoadContent method and only reference the in-memory texture in the Update method. This isn't the main reason the game is this much laggy, but it is an unnecessary overhead.
I am working on my game using XNA. I have found a series of tutorials by Oyyou from YouTube and have gone to the collision tutorial so far. I have successfully processed gravity, movement and animation. But I have a problem with collision. The spawn point of my character is up in the air.
The first value is my bool hasJumped. And the second is y velocity. It is accelerating by 0.25.
The character is falling down slowly accelerating. All four platforms are made the same way. All four are in the list and I don't make anything to work with any of them particularly.
When I land on the lowest (ground) I get the parameters I need. hasJumped is false and velocity.Y is 0.
But when I'm on one of three non-ground platforms results are not as I want them. The velocity is 0.25 even though I am making it 0. And hasJumped doesn't become true because my velocity is a non-zero variable. Unluckily I can't post images so I can't show it. But I will post my code:
this is the maingame class where I add players and platforms.
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
player = new Animation(Content.Load<Texture2D>("player"), Content.Load<Texture2D>("rect"), new Vector2(300 + 28, graphics.PreferredBackBufferHeight - 500), 47, 44, graphics.PreferredBackBufferHeight, graphics.PreferredBackBufferWidth);
platformList.Add(new Platform(Content.Load<Texture2D>("Crate"), new Vector2(300,graphics.PreferredBackBufferHeight-100), 80,50));
platformList.Add(new Platform(Content.Load<Texture2D>("Crate"), new Vector2(500, graphics.PreferredBackBufferHeight - 50), 80, 50));
platformList.Add(new Platform(Content.Load<Texture2D>("Crate"), new Vector2(700, graphics.PreferredBackBufferHeight - 60),80,50));
platformList.Add(new Platform(Content.Load<Texture2D>("Crate"), new Vector2(0, graphics.PreferredBackBufferHeight - 10), graphics.PreferredBackBufferWidth, 10));
// TODO: use this.Content to load your game content here
}
This is my Animation class:
class Animation
{
Texture2D texture;
Texture2D rectText;
public Rectangle rectangle;
public Rectangle collisionRect;
public Vector2 position;
Vector2 origin;
public Vector2 velocity;
int currentFrame;
int frameHeight;
int frameWidth;
int screenHeight;
int screenWidth;
float timer;
float interval = 60;
bool movingRight;
public bool hasJumped;
public Animation(Texture2D newTexture, Texture2D newRectText, Vector2 newPosition, int newHeight, int newWidth, int screenH, int screenW)
{
rectText = newRectText;
texture = newTexture;
position = newPosition;
frameHeight = newHeight;
frameWidth = newWidth;
screenHeight = screenH;
screenWidth = screenW;
hasJumped = true;
}
public void Update(GameTime gameTime)
{
rectangle = new Rectangle(currentFrame * frameWidth, 0, frameWidth, frameHeight);
collisionRect = new Rectangle((int)position.X-frameWidth/2, (int)position.Y - frameHeight/2, frameWidth, frameHeight);
origin = new Vector2(rectangle.Width / 2, rectangle.Height / 2);
position = position + velocity;
if (Keyboard.GetState().IsKeyDown(Keys.Right))
{
AnimateRight(gameTime);
velocity.X = 5;
movingRight = true;
}
else if (Keyboard.GetState().IsKeyDown(Keys.Left))
{
AnimateLeft(gameTime);
velocity.X = -5;
movingRight = false;
}
else
{
velocity.X = 0f;
if (movingRight)
currentFrame = 0;
else currentFrame = 4;
}
if(Keyboard.GetState().IsKeyDown(Keys.Space) && !hasJumped)
{
position.Y -= 5f;
velocity.Y = -10;
hasJumped = true;
}
if(hasJumped)
{
velocity.Y += 0.25f;
}
if(position.X<0+frameWidth/2)
{
position.X = 0 + frameWidth / 2;
}
else if (position.X>screenWidth-frameWidth/2)
{
position.X = screenWidth - frameWidth / 2;
}
}
public void AnimateRight(GameTime gameTime)
{
timer += (float)gameTime.ElapsedGameTime.TotalMilliseconds/2;
if(timer>interval)
{
currentFrame++;
timer = 0;
if (currentFrame > 3)
{
currentFrame = 0;
}
}
}
public void AnimateLeft(GameTime gameTime)
{
timer += (float)gameTime.ElapsedGameTime.TotalMilliseconds / 2;
if (timer > interval)
{
currentFrame++;
timer = 0;
if (currentFrame > 7 || currentFrame < 4)
{
currentFrame = 4;
}
}
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(texture,position,rectangle,Color.White, 0f, origin, 1.0f, SpriteEffects.None, 0);
// spriteBatch.Draw(rectText,collisionRect,Color.White);
}
}}
The platform class is pretty simple:
class Platform
{
Texture2D texture;
Vector2 position;
public Rectangle rectangle;
public Platform(Texture2D newTexture, Vector2 newPosition, int platformWidth, int platformHeight)
{
texture = newTexture;
position = newPosition;
rectangle = new Rectangle((int)position.X, (int)position.Y, platformWidth, platformHeight);
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(texture, rectangle, Color.White);
}
}
and the collision method:
public static bool isOnTopOf(this Rectangle r1, Rectangle r2)
{
return (r1.Bottom >= r2.Top - 10 &&
r1.Bottom <= r2.Top + 10 &&
r1.Right >= r2.Left + 10 &&
r1.Left <= r2.Right - 10);
}
The problem is supposed to be here:
foreach (Platform a in platformList)
{
if (player.collisionRect.isOnTopOf(a.rectangle) && player.velocity.Y>=0)
{
player.hasJumped = false;
player.velocity.Y = 0f;
if(player.collisionRect.Bottom > a.rectangle.Top || player.collisionRect.Bottom - a.rectangle.Top <=10)
{
player.position.Y = a.rectangle.Y - 48 / 2;
player.hasJumped = false;
}
}
else
{
player.hasJumped = true;
}
}
But if I exclude the last else it won't fall of the platform.
Thank you for upvoting the question. I have added images.
Your problem is that when the user is on top of a platform that is not the lowest one, during the else when you check if the user is on a platform, then you explicitly set the hasJumped to true.
What you must do is in your foreach where you check your platforms, to order them by INCREASING Y-coordinate (very much depending on your camera settings) and break after you set hasJumped to false. This way you will avoid your issue:
foreach (Platform a in platformList.OrderByY())
{
if (player.collisionRect.isOnTopOf(a.rectangle) && player.velocity.Y>=0)
{
player.hasJumped = false;
player.velocity.Y = 0f;
if(player.collisionRect.Bottom > a.rectangle.Top || player.collisionRect.Bottom - a.rectangle.Top <=10)
{
player.position.Y = a.rectangle.Y - 48 / 2;
player.hasJumped = false;
}
break;
}
else
{
player.hasJumped = true;
}
}
Unfortunately, it is often the case with 3D development that we have to do some hacks to get the application to render correctly. This is especially the case when rendering a complex item with advanced transparencies. In your case however, I would advise to re-imagine the way you work with collisions.
Games development is not an easy task. Superficially, the constraints under which you are working enforce a less than ideal architecture. Everything in an XNA game revolves around the update loop and the ability to control which item gets updated first is so easy and tempting that people tend to use that. It is however generally a much better approach to try and extrapolate functionality in such a way that your models behave in an event-driven way. One way to achieve this is to split the update cycle of your game in the following phases:
Input Phase: Retrieve input from the user and handle them as events (these can be simple method calls on items in a method other than Update or a more complex but better method like using Rx)
Movement Phase: Develop some physical characteristics in your models (acceleration, velocity, weight, etc.) and letting them do the work of positioning, rotating on their own during the movement phase. This is the only thing that they should be doing in Update.
Collision Phase: Test for collision and then fire events on the objects to handle collision.
Cleanup Phase: Cleanup any problems, like moving inside a wall during the collision detection phase. or phasing out particles etc. This gets important when you have requirements to draw on exact pixels to avoid blurring etc.
The above is not necessarily the best way to do it, but it works. If you rely only on the update cycle you will very soon reach a point where the interdependencies between models and the requirement to have some events fired in order will be a nightmare to support. Enforcing an event driven mechanism will save you from a lot of scrapped work with a very small initial overhead.
My suggestion to use Rx may sound a little strange for an XNA game, but trust me, it is an awesome way to work with events. Finally, I would like to mention MonoGame, an excellent framework to develop games for Windows, Mac, Linux, Android, iPhone, Windows Phone, WinRT (and even more) if you do not already know it.
Firstly, I would like to say sorry for making another thread asking the same question (more or less), but I am desperate for an answer and the other thread went dead.
I am currently working on a project for school in which I am attempting to make a simple 2d shooter. Problem is, I don't know how to implement collision detection between my two lists (being bullets and enemies as stated in title). I am very new to programming and have been using various tutorials as a guide, some tutorials say to use a nested for loop and if statement while I have seen others using an if statement, oh and I'm using the rectangle collision method not the pixel by pixel one I think it was called. Thanks in advance! :)
Here is my code:
Main:
namespace Software_Design_Major_Project
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D ship; // Declaring the sprite
Vector2 shipposition = Vector2.Zero; // Creating a vector for the sprite.
List<bullets> bullets = new List<bullets>(); // a list is created here so that there can be multiple copies of this item at once without writing the extra code.
Texture2D texture;
KeyboardState pastkey;
//bullet sound effect.
SoundEffect effect;
List<enemies> Enemies = new List<enemies>();
Random random2 = new Random();
float spawn = 0;
public enum GameState
{
MainMenu,
Playing,
}
GameState CurrentGameState = GameState.MainMenu;
int screenWidth = 600, screenHeight = 480;
cButton play;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
//changes width of screen to 600px.
graphics.PreferredBackBufferWidth = 600;
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
// This statement positions the ship.
ship = Content.Load<Texture2D>("ship"); // Loads the ship into the memory.
shipposition = new Vector2((graphics.GraphicsDevice.Viewport.Width / 2) - (ship.Width / 2), 420);
// loads bullet sprite
texture = Content.Load<Texture2D>("bullet");
graphics.PreferredBackBufferWidth = screenWidth;
graphics.PreferredBackBufferHeight = screenHeight;
graphics.ApplyChanges();
IsMouseVisible = true;
play = new cButton(Content.Load<Texture2D>("play"), graphics.GraphicsDevice);
play.setPosition(new Vector2(225, 220));
effect = Content.Load<SoundEffect>("laser");
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
spawn += (float)gameTime.ElapsedGameTime.TotalSeconds;
// spawns enemy every second.
foreach (enemies enemy in Enemies)
enemy.update(graphics.GraphicsDevice);
MouseState mouse = Mouse.GetState();
switch (CurrentGameState)
{
case GameState.MainMenu:
if (play.isClicked == true)
CurrentGameState = GameState.Playing;
play.Update(mouse);
break;
case GameState.Playing:
if (Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.E))
{
Exit();
}
break;
}
// Allows the ship to move left and stops the ship going off the screen.
if (Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.Left) && shipposition.X >= 0)
{
shipposition.X -= 7;
}// same as above except for the right direction.
if (Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.Right) && shipposition.X < ((graphics.GraphicsDevice.Viewport.Width) - (ship.Width)))
{
shipposition.X += 7;
}
// this prevents the player from holding down space to spam bullets.
if (Keyboard.GetState().IsKeyDown(Keys.Space) && pastkey.IsKeyUp(Keys.Space))
{
bullets bullet = new bullets(texture);
// the ships coordinates are gathered from the top left hand corner of the sprites rectangle therefore 'new Vector2(shipposition.X + 32, shipposition.Y)' had to
// be added rather than just = 'shipposition' to avoid having the bullets shoot from the wing.
bullet.position = new Vector2(shipposition.X + 32, shipposition.Y);
bullets.Add(bullet);
effect.Play();
}
pastkey = Keyboard.GetState();
//calls upon the update method from the bullets class.
foreach (bullets bullet in bullets)
bullet.update();
LoadEnemies();
base.Update(gameTime);
}
public void LoadEnemies()
{
int randX = random2.Next(10, 540);
if (spawn <= 1)
{
spawn = 0;
//limits amount of enemies on screen to 5.
if (Enemies.Count() < 5)
Enemies.Add(new enemies(Content.Load<Texture2D>("enemy"), new Vector2(randX, -100)));
}
for (int i = 0; i < Enemies.Count; i++)
{
if (!Enemies[i].enemyVisble)
{
//removes the enemies when they go off screen.
Enemies.RemoveAt(i);
i--;
}
}
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
// calls draw method in bullets class
foreach (bullets bullet in bullets)
{
bullet.Draw(spriteBatch);
}
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend);
spriteBatch.Draw(ship, shipposition, Color.White); // draws ship sprite
switch (CurrentGameState)
{
case GameState.MainMenu:
play.draw(spriteBatch);
spriteBatch.Draw(Content.Load<Texture2D>("menu"), new Rectangle(0, 0, screenWidth, screenHeight), Color.White);
break;
case GameState.Playing:
break;
}
foreach (enemies enemy in Enemies)
{
enemy.draw(spriteBatch);
}
spriteBatch.End();
base.Draw(gameTime);
}
}
}
Bullets Class:
namespace Software_Design_Major_Project
{
class bullets // A new class needs to be created to allow for bullets.
{
public Texture2D texture;
public Vector2 position;
public bool isvisible;
public bullets(Texture2D newtexture)
{
texture = newtexture;
isvisible = false;
}
public void update()
{
position.Y -= 3; // velocity of the bullet
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Begin();
spriteBatch.Draw(texture, position, Color.White);
spriteBatch.End();
}
}
}
Enemies Class:
namespace Software_Design_Major_Project
{
public class enemies
{
public Texture2D enemyTexture;
public Vector2 enemyPosition;
public bool enemyVisble = true;
public float enemyMoveSpeed;
public int Value;
Random random = new Random();
int randY;
public enemies (Texture2D newEnemyTexture, Vector2 newEnemyPosition)
{
enemyTexture = newEnemyTexture;
enemyPosition = newEnemyPosition;
randY = random.Next(1, 4);
enemyMoveSpeed = randY;
enemyVisble = true;
Value = 100;
}
public void update(GraphicsDevice graphics)
{
enemyPosition.Y += enemyMoveSpeed;
if (enemyPosition.Y > 500)
enemyVisble = false;
}
public void draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(enemyTexture, enemyPosition, Color.White);
enemyVisble = true;
}
}
}
You have several ways to do it... one of them maybe add a radio property to enemies and bullets....
for (int bi=0; bi<bullets.count; )
{
bool should_destroy_bullet = false;
Bullet b = bullets[bi];
for (int ei=0; ei<enemies.count; )
{
Enemy e = ememies[ei];
if (b.radio + e.radio < Vector2.Distance(b.Pos, e.Pos)) // Check collision
{
e.Died();
enemies[ei] = enemies[enemies.Count-1];
enemies.RemoveAt(enemies.Count-1);
should_destroy_bullet = true; // This lets a bullet kill more than one enemy
} else ei++;
}
if (should_destroy_bullet) {
b.Died();
bullets[bi] = bullets[bullets.count-1];
bullets.RemoveAt(bullets.count-1);
} else bi++;
}
Or you can build a rectangle for each sprite and check if they intersects....
if (b.Bounds.Intersects(e.Bounds)) ....
The Pythagorean theorem could work for you.(A squared plus B squared = C squared)
Make your players and enemies have a radius.Put this in your constructor.
public float radius = 15;
Put the following in a update void/subclass so that it happens every second.
Make a float the X location of your player and subtract the X location of the bullet. Square it.
float XDist = Math.Pow(player1.location.X - bullet.location.X,2);
Make a float the Y location of your player and subtract the Y location of the bullet.Square it.
float YDist = Math.Pow(player1.location.X - bullet.location.X,2);
Make a float to figure out the square root of the sum of Xdist and Ydist.
float actualDist = Math.Sqrt(Xdist + Ydist);
Now if the radius of your player is less than the distance between the player and the bullet, the bullet has hit the player.
if(actualDist < radius)
bullethit == true;
This is my first post at this section (XNA and game development). I'm trying to get something the below image. As you can see, there's a highway and inside of it, there'll be some objects moving (millisecond). I guess the streeth behavier is like a pipeline. When the highway loads an object, it appears at the beggining and it'll be moving through the highware until it arrives in the another extreme of the highway.
My main problem is, how can I do to move several objects only inside of the highway?
Thanks in advance.
You need a list of points and a list of sprites
class Path
{
List<Vector2> Points;
float[] Lengths;
Vector2[] Directions;
void Build()
{
Lengths = new float[Points.Count-1];
Directions = new float[Points.Count-1];
for (int i=0; i<Points.Count-1;i++)
{
Directions[i] = Points[i+1] - Points[i];
Lengths[i] = Directions[i].Length();
Directions[i].Normalize();
}
}
}
class Sprite
{
Vector2 Position;
float StagePos;
int StageIndex;
Path Path;
float Speed;
void Update(float Seconds)
{
if (StageIndex!=Path.Points.Count-1)
{
StagePos += Speed * Seconds;
while (StagePos>Path.Lengths[StageIndex])
{
StagePos -= Path.Lengths[StageIndex];
StageIndex++;
if (StageIndex == Path.Points.Count-1)
{
Position = Path.Points[StageIndex];
return;
}
}
Position = Path.Points[StageIndex] + Directions[StageIndex] * StagePos;
}
}
}