My bullets never draw on screen? - c#

I'm making a Space Invaders copy in XNA. I have my playerShip class that handles movement and sprite animation. Today I decided to make my ship shoot. I created a class to hold my bullets logic and initialized/updated them in my playShip class. So my problem is that when I build and debug, I press the key for shooting (in my case, X) but the bullets are never drawn on the screen. I've put a breakpoint on my Draw() call and there wasn't an exception. This means the code was never executed. Here is my ship class:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Storage;
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.Net;
namespace SpaceInvaders
{
class playerShip
{
public static Texture2D playerShipTex, bulletsTex;
public static Rectangle playerShipHitBox;
public static Vector2 playerShipPos = new Vector2(369, 546), playerShipOrigin;
int playerShipCurrentFrame = 1, playerShipFrameWidth = 62, playerShipFrameHeight = 86;
public float spriteTimer = 0f, spriteInterval = 100f, bulletDelay;
public List<blasterLasers> bulletsList;
public playerShip()
{
bulletsList = new List<blasterLasers>();
bulletDelay = 20f;
}
public void LoadContent(ContentManager Content)
{
playerShipTex = Content.Load<Texture2D>(".\\gameGraphics\\gameSprites\\playerShip\\playerShipSpriteSheet");
bulletsTex = Content.Load<Texture2D>(".\\gameGraphics\\gameSprites\\playerShip\\playerShipBlaster");
}
public void Update(GameTime gameTime)
{
playerShipHitBox = new Rectangle(playerShipCurrentFrame * playerShipFrameWidth, 0, playerShipFrameWidth, playerShipFrameHeight);
playerShipOrigin = new Vector2(playerShipHitBox.X / 2, playerShipHitBox.Y / 2);
MouseState mouseState = Mouse.GetState();
KeyboardState keyboardState = Keyboard.GetState();
spriteTimer += (float)gameTime.ElapsedGameTime.Milliseconds;
if (spriteTimer > spriteInterval)
{
playerShipCurrentFrame++;
spriteTimer = 0f;
}
if (playerShipCurrentFrame == 2)
{
playerShipCurrentFrame = 0;
}
playerShipHitBox = new Rectangle(playerShipCurrentFrame * playerShipFrameWidth, 0, playerShipFrameWidth, playerShipFrameHeight);
playerShipOrigin = new Vector2(playerShipHitBox.Width / 2, playerShipHitBox.Height / 2);
if (keyboardState.IsKeyDown(Keys.X))
{
Shoot();
}
UpdateBullets();
if (keyboardState.IsKeyDown(Keys.Right))
{
playerShipPos.X += 3;
}
if (keyboardState.IsKeyDown(Keys.Left))
{
playerShipPos.X -= 3;
}
if (keyboardState.IsKeyDown(Keys.Down))
{
playerShipPos.Y += 3;
}
if (keyboardState.IsKeyDown(Keys.Up))
{
playerShipPos.Y -= 3;
}
if (playerShipPos.X <= 0)
{
playerShipPos.X = 0;
}
if (playerShipPos.X + playerShipTex.Width >= 1110)
{
playerShipPos.X = 1110 - playerShipTex.Width;
}
if (playerShipPos.Y <= 48)
{
playerShipPos.Y = 48;
}
if (playerShipPos.Y + playerShipTex.Height >= Game1.screenHeight)
{
playerShipPos.Y = Game1.screenHeight - playerShipTex.Height;
}
}
public void Shoot()
{
if (bulletDelay >= 0)
{
bulletDelay--;
}
if (bulletDelay <= 0)
{
blasterLasers newBullet = new blasterLasers(bulletsTex);
newBullet.spritePos = new Vector2(playerShipPos.X + 14 - newBullet.spriteTex.Width / 2, playerShipPos.Y);
newBullet.isVisible = true;
if (bulletsList.Count() > 20)
{
bulletsList.Add(newBullet);
}
}
if (bulletDelay == 0)
{
bulletDelay = 20;
}
}
public void UpdateBullets()
{
foreach (blasterLasers bulletsSpawn in bulletsList)
{
bulletsSpawn.spritePos.Y = bulletsSpawn.spritePos.Y - bulletsSpawn.spriteSpeed;
if (bulletsSpawn.spritePos.Y == 0)
{
bulletsSpawn.isVisible = false;
}
}
for (int i = 0; i < bulletsList.Count(); i++)
{
if (!bulletsList[i].isVisible)
{
bulletsList.RemoveAt(i);
i--;
}
}
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(playerShipTex, playerShipPos, playerShipHitBox, Color.White, 0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0);
foreach (blasterLasers bulletsSpawn in bulletsList)
{
bulletsSpawn.Draw(spriteBatch);
}
}
}
}
And here's my blaster class:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Storage;
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.Net;
namespace SpaceInvaders
{
public class blasterLasers
{
public Rectangle boundingBox;
public Texture2D spriteTex;
public Vector2 spriteOrigin, spritePos;
public bool isVisible;
public float spriteSpeed;
public blasterLasers(Texture2D newSpriteTex)
{
spriteSpeed = 10f;
spriteTex = newSpriteTex;
isVisible = false;
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(spriteTex, spritePos, Color.White);
}
}
}
And finally I initalize the playerShip class and Update()/Draw() it in my Game1 class.

I don't understand this line if (bulletsList.Count() > 20). What does it do? I mean, if there is no bullets already on the field, you can't fire new ones?
-- OTHER PROBLEM
Then you ask if if (bulletsSpawn.spritePos.Y == 0). But position.Y is never 0, it's only above 0 or goes under 0. So change that == to <=

Related

How can I make the float variable to take affect also in the Update?

How to make the variable lightenAmount to be affect the changes to apply the changes in the Update ?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class RawImagePixelsChange : MonoBehaviour
{
RawImage myImage;
public Texture2D origTex;
public Texture2D newTex;
[Range(-1, 1)]
public float lightenAmount = 0.1f;
Color[] pixels;
void Start()
{
var texture = GetComponent<RawImage>().texture;
origTex = texture as Texture2D;
myImage = GetComponent<RawImage>();
if (texture != null && origTex != null)
{
pixels = origTex.GetPixels();
newTex = new Texture2D(origTex.width, origTex.height);
newTex.SetPixels(pixels);
newTex.Apply();
myImage.texture = newTex;
}
}
public void modifyPixels(float lightenAmount) // Press "P" to change pixel colors by lightenAmount
{
for (int i = 0; i < pixels.Length; i++)
{
pixels[i].r += lightenAmount;
if (pixels[i].r > 1) pixels[i].r = 1;
if (pixels[i].r < 0) pixels[i].r = 0;
pixels[i].g += lightenAmount;
if (pixels[i].g > 1) pixels[i].g = 1;
if (pixels[i].g < 0) pixels[i].g = 0;
pixels[i].b += lightenAmount;
if (pixels[i].b > 1) pixels[i].b = 1;
if (pixels[i].b < 0) pixels[i].b = 0;
}
newTex.SetPixels(pixels);
newTex.Apply();
}
public void restorePixels()
{
pixels = origTex.GetPixels();
newTex.SetPixels(pixels);
newTex.Apply();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.P))
{
modifyPixels(lightenAmount);
}
if (Input.GetKeyDown(KeyCode.O))
{
restorePixels();
}
}
}
I want that when I change the variable lightenAmount value in run time to take affect of it also in the Update. Now it's only affects the changes when starting the game.
I'm using the variable value later in other script and it's not affecting the changes.
I'm trying to use this variable value in this script :
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class MouseHover : MonoBehaviour
{
public RawImagePixelsChange rawImagePixelsChange;
public static string savedGameFName;
public static string folder;
public static bool loadingwithfolder = false;
private bool loadGame = false;
// Reference the according RawImage here via the Inspector
[SerializeField] private RawImage rawImage;
private void Awake()
{
if (!rawImage) rawImage = GetComponent<RawImage>();
}
private void Start()
{
}
public void OnHover()
{
rawImagePixelsChange.modifyPixels(rawImagePixelsChange.lightenAmount);
PlaySoundEffect();
loadGame = true;
}
public void OnHoverExit()
{
rawImagePixelsChange.restorePixels();
loadGame = false;
}
private void Update()
{
if (loadGame)
{
if (Input.GetMouseButtonDown(0))
{
var name = transform.gameObject.GetComponent<RawImageInfo>().FolderAndFileName;
int index = name.IndexOf(".png");
string res = name.Substring(index);
string res1 = name.Substring(0, name.Length - (name.Length - index));
string res2 = res1 + ".savegame.txt";
savedGameFName = res2;//#"D:\Unity Projects\The Kid From Space Backup_001\Assets\save_//res2//savegame.txt";
loadingwithfolder = true;
folder = Path.GetDirectoryName(savedGameFName);
}
}
}
private void PlaySoundEffect()
{
transform.GetComponent<AudioSource>().Play();
}
}
In this line :
rawImagePixelsChange.modifyPixels(rawImagePixelsChange.lightenAmount);
The solution is to create my own custom slider. The reason for creating a custom slider is because the Range attribute should not be working at run time. The easiest way is to create a custom slider.
In the first script I removed the Range attribute :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class RawImagePixelsChange : MonoBehaviour
{
RawImage myImage;
public Texture2D origTex;
public Texture2D newTex;
public float lightenAmount = 0.1f;
Color[] pixels;
void Start()
{
var texture = GetComponent<RawImage>().texture;
origTex = texture as Texture2D;
myImage = GetComponent<RawImage>();
if (texture != null && origTex != null)
{
pixels = origTex.GetPixels();
newTex = new Texture2D(origTex.width, origTex.height);
newTex.SetPixels(pixels);
newTex.Apply();
myImage.texture = newTex;
}
}
public void modifyPixels(float lightenAmount)
{
for (int i = 0; i < pixels.Length; i++)
{
pixels[i].r += lightenAmount;
if (pixels[i].r > 1) pixels[i].r = 1;
if (pixels[i].r < 0) pixels[i].r = 0;
pixels[i].g += lightenAmount;
if (pixels[i].g > 1) pixels[i].g = 1;
if (pixels[i].g < 0) pixels[i].g = 0;
pixels[i].b += lightenAmount;
if (pixels[i].b > 1) pixels[i].b = 1;
if (pixels[i].b < 0) pixels[i].b = 0;
}
newTex.SetPixels(pixels);
newTex.Apply();
}
public void restorePixels()
{
pixels = origTex.GetPixels();
newTex.SetPixels(pixels);
newTex.Apply();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.P))
{
modifyPixels(lightenAmount);
}
if (Input.GetKeyDown(KeyCode.O))
{
restorePixels();
}
}
public float Amount()
{
return lightenAmount;
}
}
Then created a simple small editor script :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.UIElements;
[CustomEditor(typeof(RawImagePixelsChange))]
public class CustomSlider : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
RawImagePixelsChange rawimagepixelschange = (RawImagePixelsChange)target;
rawimagepixelschange.lightenAmount = EditorGUILayout.Slider(
rawimagepixelschange.lightenAmount, -1f, 1f);
}
}
And now when changing the slider value in run time it's also changing the lightenAmount value and then when the mouse is enter the OnHover it's changing the pixels color according to the slider value.
Working perfect.

Unable to get objects to collide

For the life of me, I cannot figure out what I am doing wrong. I have managed to make a player and make it shoot. I've also managed to make balls spawn in at random locations/speeds in the picture box.
I can't get any Collision to work. I am trying to keep all balls in the picture box and bounce back and also bounce off each other, and then destroy them when shot.
I have been trying to use Ball.Bounds.IntersectsWith(pictureBox2.Bounds), but it seems that Ball.bounds is wrong.
I have a vague idea why it is wrong but not definitive. My property bounds in box.cs is either wrong or I don't know how to make that relate to positioning all my balls.
A little nudge in the right direction would be appreciated as I have been stuck on this issue for a while now.
ball.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace shootyarcher
{
class Ball : Box
{
public string bounds { get; set; }
static private Random generator = new Random();
private int countdown;
public Ball ()
{
pic = Properties.Resources.Balloon;
x = generator.Next(60, 1920);
y = generator.Next(100, 1000);
xspeed = generator.Next(-10, 4);
yspeed = generator.Next(-10, 4);
countdown = generator.Next(100, 200);
}
public new void Move()
{
countdown--;
if (countdown == 0)
{
xspeed = generator.Next(-4, 4);
yspeed = generator.Next(-4, 4);
countdown = generator.Next(20, 40);
}
x = x + xspeed;
y = y + yspeed;
}
}
}
box.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing; //pictures
namespace shootyarcher
{
class Box
{
public float x;
public float y;
public float w;
public float h;
public float xspeed;
public float yspeed;
public Image pic;
public Box() // constructor
{
x = 0;
y = 0;
xspeed = 0;
yspeed = 0;
}
public void Move()
{
x = x + xspeed;
y = y + yspeed;
}
public void Draw(Graphics g)
{
g.DrawImage (pic, x, y);
}
public float Width()
{
return pic.Width;
}
public float Height()
{
return pic.Height;
}
public float Left()
{
return x;
}
public float Right()
{
return x + Width();
}
public float Top()
{
return y;
}
public float Bottom()
{
return y + Height();
}
}
}
Form1.cs
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
namespace shootyarcher
{
public partial class Form1 : Form
{
Archer player;
List<Arrow> Shiv;
List<Ball> Kill;
public Form1()
{
InitializeComponent();
Cursor.Hide();
this.FormBorderStyle = FormBorderStyle.None;
this.TopMost = true;
this.Bounds = Screen.PrimaryScreen.Bounds;
player = new Archer(0, 0);
Shiv = new List<Arrow>();
Kill = new List<Ball>();
for (int i = 0; i < 400; i++)
{
Ball temp = new Ball();
Kill.Add(temp);
}
}
private void timer1_Tick(object sender, EventArgs e)
{
player.Move();
foreach (Arrow t in Shiv)
{
t.Move();
}
foreach (Ball m in Kill)
{
m.Move();
}
pictureBox1.Invalidate();
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.W)
{
player.moveup = true;
}
if (e.KeyCode == Keys.S)
{
player.movedown = true;
}
if (e.KeyCode == Keys.Space)
{
Arrow temp = new Arrow(player.x, player.y);
Shiv.Add(temp);
}
if (e.KeyCode == Keys.Escape)
{
this.Close();
}
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.W)
{
player.moveup = false;
}
if (e.KeyCode == Keys.S)
{
player.movedown = false;
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
player.Draw(e.Graphics);
foreach (Arrow t in Shiv)
{
t.Draw(e.Graphics);
}
foreach (Ball m in Kill)
{
m.Draw(e.Graphics);
}
}
}
}

C# XNA - randomly draw a texture on the top X axis

So I'm making a space invaders game. I want to have meteors spawning from different/random locations on the entire 0 coordinate of X. How should I ahieve this? I've seen people using Lists and Random()s but I need a code for my meteorGenerator class. Then I'll call it's methods in Game1
When the meteors are drawn they should fall down at the bottom of the screen and disappear.
I saw an answer here on SO and implemented it to my class:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Storage;
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.Net;
namespace SpaceInvaders
{
class meteorGenerator
{
public static Vector2 m_Pos;
public Vector2 m_Position
{
get { return m_Pos; }
set { m_Pos = value; }
}
Texture2D m_Texture { get; set; }
Texture2D m_MeteorsTex;
public meteorGenerator(Texture2D m_Tex, Vector2 m_Pos)
{
m_Position = m_Pos;
m_Texture = m_Tex;
}
List<meteorGenerator> m_MeteorsList = new List<meteorGenerator>();
static readonly Random rnd = new Random();
public void LoadContent(ContentManager Content)
{
m_MeteorsTex = Content.Load<Texture2D>(".\\gameGraphics\\gameSprites\\thePlan\\meteorSpawn");
}
public void Update(GameTime gameTime)
{
if (m_MeteorsList.Count() < 4)
{
m_MeteorsList.Add(new meteorGenerator(m_MeteorsTex, new Vector2(rnd.Next(30, 610), rnd.Next(30, 450))));
}
}
public void Draw(SpriteBatch spriteBatch)
{
foreach (meteorGenerator m_Meteor in m_MeteorsList)
{
spriteBatch.Draw(m_Meteor.m_Texture, m_Meteor.m_Position, Color.White);
}
}
}
}
But when I try to instance the constructor of the class in Game1 I get an error:
meteorGenerator m_MeteorGenerator;
protected override void Initialize()
{
// TODO: Add your initialization logic here.
m_MeteorGenerator = new meteorGenerator(meteorGenerator.m_Tex, meteorGenerator.m_Pos);
}
Error 1 'SpaceInvaders.meteorGenerator' does not contain a definition for 'm_Tex'
I think this will do the trick.
I renamed the parameters for the constructor to vTexture and vPos but I agree with the comments this is old style coding and very confusing. Now we would use
public Vector2 position
public Vector2 Position
{
get { return position }
set { position = value; }
}
public meteorGenerator(Texture2D texture, Vector2 position)
{
Position = texture;
Texture = position;
}
But that is splitting hairs for now.
What I did change is m_MeteorsList, LoadContent, Update and Draw are now static.
you can just call
meteorGenerator.Loadcontent(Content) // to load your content
meteorGenerator.Update(gameTime) // will generate the meteors
meteorGenerator.Draw(spriteBatch) // will draw them.
No need to have multiple instances of the meteorGenerator class.
I honestly don't think this good practice as I would have used a separate Meteor class or struct to store information about meteors.
namespace SpaceInvaders
{
class meteorGenerator
{
public Vector2 m_Pos;
public Vector2 m_Position
{
get { return m_Pos; }
set { m_Pos = value; }
}
Texture2D m_Texture { get; set; }
Texture2D m_MeteorsTex;
public meteorGenerator(Texture2D vTex, Vector2 vPos)
{
m_Position = vPos;
m_Texture = vTex;
}
static List<meteorGenerator> m_MeteorsList = new List<meteorGenerator>();
static readonly Random rnd = new Random();
public static void LoadContent(ContentManager Content)
{
m_MeteorsTex = Content.Load<Texture2D>(".\\gameGraphics\\gameSprites\\thePlan\\meteorSpawn");
}
public static void Update(GameTime gameTime)
{
if (m_MeteorsList.Count() < 4)
{
m_MeteorsList.Add(new meteorGenerator(m_MeteorsTex, new Vector2(rnd.Next(30, 610), rnd.Next(30, 450))));
}
}
public static void Draw(SpriteBatch spriteBatch)
{
foreach (meteorGenerator m_Meteor in m_MeteorsList)
{
spriteBatch.Draw(m_Meteor.m_Texture, m_Meteor.m_Position, Color.White);
}
}
}
}

Display vector co-ordinates as String values [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
I am right now trying to display a vector holding an X and Y value, for a sprite, from one class Game Object.cs to Game1.cs. I move a protected value (protected Vector2 velocity;) to a public Vector2 velocity when I move it over the draw method (so that it will show how fast the sprite on screen is moving) it comes up with Error 1 An object reference is required for the non-static field, method, or property. So I add static, now it's public static Vector2 velocitys, and play the game. When I look at the X and Y value, they'er there but will not change when I move. I have had this problem on anything with a static.
Is there a way to get rid of the static, or fix this so I can see the X and Y update while I am playing? I have the velocitys Vector take velocity's X and Y in the update in GameObject.cs so that it will constantly take from velocity.
Why does it need a static? Can I change that? Can I update it on the screen?
This is the code:
GameObject.cs:
(Holdes the Vectors velocitys and velocity)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Tile_Engine;
namespace **
{
public class GameObject
{
#region Declarations
protected Vector2 worldLocation;
protected Vector2 velocity;
protected int frameWidth;
protected int frameHeight;
protected bool enabled;
protected bool flipped = false;
protected bool onGround;
protected Rectangle collisionRectangle;
protected int collideWidth;
protected int collideHeight;
protected bool codeBasedBlocks = true;
protected float drawDepth = 0.85f;
protected Dictionary<string, AnimationStrip> animations =
new Dictionary<string, AnimationStrip>();
protected string currentAnimation;
public Vector2 velocitys;
#endregion
#region Properties
public bool Enabled
{
get { return enabled; }
set { enabled = value; }
}
public Vector2 WorldLocation
{
get { return worldLocation; }
set { worldLocation = value; }
}
public Vector2 WorldCenter
{
get
{
return new Vector2(
(int)worldLocation.X + (int)(frameWidth / 2),
(int)worldLocation.Y + (int)(frameHeight / 2));
}
}
public Rectangle WorldRectangle
{
get
{
return new Rectangle(
(int)worldLocation.X,
(int)worldLocation.Y,
frameWidth,
frameHeight);
}
}
public Rectangle CollisionRectangle
{
get
{
return new Rectangle(
(int)worldLocation.X + collisionRectangle.X,
(int)worldLocation.Y + collisionRectangle.Y,
collisionRectangle.Width,
collisionRectangle.Height);
}
set { collisionRectangle = value; }
}
#endregion
#region Helper Methods
private void updateAnimation(GameTime gameTime)
{
if (animations.ContainsKey(currentAnimation))
{
if (animations[currentAnimation].FinishedPlaying)
{
PlayAnimation(animations[currentAnimation].NextAnimation);
}
else
{
animations[currentAnimation].Update(gameTime);
}
}
}
#endregion
#region Public Methods
public void PlayAnimation(string name)
{
if (!(name == null) && animations.ContainsKey(name))
{
currentAnimation = name;
animations[name].Play();
}
}
public virtual void Update(GameTime gameTime)
{
if (!enabled)
return;
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
updateAnimation(gameTime);
if (velocity.Y != 0)
{
velocitys = velocity;
onGround = false;
}
Vector2 moveAmount = velocity * elapsed;
moveAmount = horizontalCollisionTest(moveAmount);
moveAmount = verticalCollisionTest(moveAmount);
Vector2 newPosition = worldLocation + moveAmount;
newPosition = new Vector2(
MathHelper.Clamp(newPosition.X, 0,
Camera.WorldRectangle.Width - frameWidth),
MathHelper.Clamp(newPosition.Y, 2 * (-TileMap.TileHeight),
Camera.WorldRectangle.Height - frameHeight));
worldLocation = newPosition;
}
public virtual void Draw(SpriteBatch spriteBatch)
{
if (!enabled)
return;
if (animations.ContainsKey(currentAnimation))
{
SpriteEffects effect = SpriteEffects.None;
if (flipped)
{
effect = SpriteEffects.FlipHorizontally;
}
spriteBatch.Draw(
animations[currentAnimation].Texture,
Camera.WorldToScreen(WorldRectangle),
animations[currentAnimation].FrameRectangle,
Color.White, 0.0f, Vector2.Zero, effect, drawDepth);
}
}
#endregion
#region Map-Based Collision Detecting Methods
private Vector2 horizontalCollisionTest(Vector2 moveAmount)
{
if (moveAmount.X == 0)
return moveAmount;
Rectangle afterMoveRect = CollisionRectangle;
afterMoveRect.Offset((int)moveAmount.X, 0);
Vector2 corner1, corner2;
if (moveAmount.X < 0)
{
corner1 = new Vector2(afterMoveRect.Left,
afterMoveRect.Top + 1);
corner2 = new Vector2(afterMoveRect.Left,
afterMoveRect.Bottom - 1);
}
else
{
corner1 = new Vector2(afterMoveRect.Right,
afterMoveRect.Top + 1);
corner2 = new Vector2(afterMoveRect.Right,
afterMoveRect.Bottom - 1);
}
Vector2 mapCell1 = TileMap.GetCellByPixel(corner1);
Vector2 mapCell2 = TileMap.GetCellByPixel(corner2);
if (!TileMap.CellIsPassable(mapCell1) ||
!TileMap.CellIsPassable(mapCell2))
{
moveAmount.X = 0;
velocity.X = 0;
}
if (codeBasedBlocks)
{
if (TileMap.CellCodeValue(mapCell1) == "BLOCK" ||
TileMap.CellCodeValue(mapCell2) == "BLOCK")
{
moveAmount.X = 0;
velocity.X = 0;
}
}
return moveAmount;
}
private Vector2 verticalCollisionTest(Vector2 moveAmount)
{
if (moveAmount.Y == 0)
return moveAmount;
Rectangle afterMoveRect = CollisionRectangle;
afterMoveRect.Offset((int)moveAmount.X, (int)moveAmount.Y);
Vector2 corner1, corner2;
if (moveAmount.Y < 0)
{
corner1 = new Vector2(afterMoveRect.Left + 1,
afterMoveRect.Top);
corner2 = new Vector2(afterMoveRect.Right - 1,
afterMoveRect.Top);
}
else
{
corner1 = new Vector2(afterMoveRect.Left + 1,
afterMoveRect.Bottom);
corner2 = new Vector2(afterMoveRect.Right - 1,
afterMoveRect.Bottom);
}
Vector2 mapCell1 = TileMap.GetCellByPixel(corner1);
Vector2 mapCell2 = TileMap.GetCellByPixel(corner2);
if (!TileMap.CellIsPassable(mapCell1) ||
!TileMap.CellIsPassable(mapCell2))
{
if (moveAmount.Y > 0)
onGround = true;
moveAmount.Y = 0;
velocity.Y = 0;
}
if (codeBasedBlocks)
{
if (TileMap.CellCodeValue(mapCell1) == "BLOCK" ||
TileMap.CellCodeValue(mapCell2) == "BLOCK")
{
if (moveAmount.Y > 0)
onGround = true;
moveAmount.Y = 0;
velocity.Y = 0;
}
}
return moveAmount;
}
#endregion
}
}
Game1.cs:
(Draws the Vector2 velocity)
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 Tile_Engine;
namespace **
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Player player;
SpriteFont pericles8;
Vector2 scorePosition = new Vector2(20, 580);
enum GameState { TitleScreen, Playing, PlayerDead, GameOver };
GameState gameState = GameState.TitleScreen;
Vector2 gameOverPosition = new Vector2(350, 300);
Vector2 livesPosition = new Vector2(600, 580);
Vector2 Velocitys = new Vector2(100, 580);
Texture2D titleScreen;
float deathTimer = 0.0f;
float deathDelay = 5.0f;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
this.graphics.PreferredBackBufferWidth = 800;
this.graphics.PreferredBackBufferHeight = 600;
this.graphics.ApplyChanges();
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
TileMap.Initialize(
Content.Load<Texture2D>(#"Textures\PlatformTiles"));
TileMap.spriteFont =
Content.Load<SpriteFont>(#"Fonts\Pericles8");
pericles8 = Content.Load<SpriteFont>(#"Fonts\Pericles8");
titleScreen = Content.Load<Texture2D>(#"Textures\TitleScreen");
Camera.WorldRectangle = new Rectangle(0, 0, 160 * 48, 12 * 48);
Camera.Position = Vector2.Zero;
Camera.ViewPortWidth = 800;
Camera.ViewPortHeight = 600;
player = new Player(Content);
LevelManager.Initialize(Content, player);
}
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();
KeyboardState keyState = Keyboard.GetState();
GamePadState gamepadState = GamePad.GetState(PlayerIndex.One);
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
if (gameState == GameState.TitleScreen)
{
if (keyState.IsKeyDown(Keys.Space) ||
gamepadState.Buttons.A == ButtonState.Pressed)
{
StartNewGame();
gameState = GameState.Playing;
}
}
if (gameState == GameState.Playing)
{
player.Update(gameTime);
LevelManager.Update(gameTime);
if (player.Dead)
{
if (player.LivesRemaining > 0)
{
gameState = GameState.PlayerDead;
deathTimer = 0.0f;
}
else{
gameState = GameState.GameOver;
deathTimer = 0.0f;
}
}
}
if (gameState == GameState.PlayerDead)
{
player.Update(gameTime);
LevelManager.Update(gameTime);
deathTimer = elapsed;
if (deathTimer > deathDelay)
{
player.WorldLocation = Vector2.Zero;
LevelManager.ReloadLevel();
player.Revive();
gameState = GameState.Playing;
}
}
if (gameState == GameState.GameOver)
{
deathTimer += elapsed;
if (deathTimer > deathDelay)
{
gameState = GameState.TitleScreen;
}
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
// TODO: Add your drawing code here
spriteBatch.Begin(
SpriteSortMode.BackToFront,
BlendState.AlphaBlend);
if (gameState == GameState.TitleScreen)
{
spriteBatch.Draw(titleScreen, Vector2.Zero, Color.White);
}
if ((gameState == GameState.Playing) ||
(gameState == GameState.PlayerDead) ||
(gameState == GameState.GameOver))
{
TileMap.Draw(spriteBatch);
player.Draw(spriteBatch);
LevelManager.Draw(spriteBatch);
spriteBatch.DrawString(
pericles8,
"Score: " + player.Score.ToString(),
scorePosition,
Color.White);
spriteBatch.DrawString(
pericles8,
"Lives Remaining: " + player.LivesRemaining.ToString(),
livesPosition,
Color.White);
spriteBatch.DrawString(
pericles8,
"Velocity: " + GameObject.velocitys.ToString(),
Velocitys,
Color.White);
}
if (gameState == GameState.PlayerDead)
{
}
if (gameState == GameState.GameOver)
{
spriteBatch.DrawString(
pericles8,
"G A M E O V E R !",
gameOverPosition,
Color.White);
}
spriteBatch.End();
base.Draw(gameTime);
}
private void StartNewGame()
{
player.Revive();
player.LivesRemaining = 3;
player.WorldLocation = Vector2.Zero;
LevelManager.LoadLevel(0);
}
}
}
Player.cs:
(A part of the velocity)
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.Content;
using Microsoft.Xna.Framework.Input;
using Tile_Engine;
namespace **
{
public class Player : GameObject
{
#region Declarations
private Vector2 fallSpeed = new Vector2(0, 20);
private float moveScale = 180.0f;
private bool dead = false;
public int score = 0;
private int livesRemaining = 3;
#endregion
public bool Dead
{
get { return dead; }
}
public int Score
{
get { return score; }
set { score = value; }
}
public int LivesRemaining
{
get { return livesRemaining; }
set { livesRemaining = value; }
}
public void Kill()
{
PlayAnimation("die");
LivesRemaining--;
velocity.X = 0;
dead = true;
}
public void Revive()
{
PlayAnimation("idle");
dead = false;
}
#region Constructor
public Player(ContentManager content)
{
animations.Add("idle",
new AnimationStrip(
content.Load<Texture2D>(#"Textures\Sprites\Player\Idle"),
48,
"idle"));
animations["idle"].LoopAnimation = true;
animations.Add("run",
new AnimationStrip(
content.Load<Texture2D>(#"Textures\Sprites\Player\Run"),
48,
"run"));
animations["run"].LoopAnimation = true;
animations.Add("jump",
new AnimationStrip(
content.Load<Texture2D>(#"Textures\Sprites\Player\Jump"),
48,
"jump"));
animations["jump"].LoopAnimation = false;
animations["jump"].FrameLength = 0.08f;
animations["jump"].NextAnimation = "idle";
animations.Add("die",
new AnimationStrip(
content.Load<Texture2D>(#"Textures\Sprites\Player\Die"),
48,
"die"));
animations["die"].LoopAnimation = false;
frameWidth = 48;
frameHeight = 48;
CollisionRectangle = new Rectangle(9, 1, 30, 46);
drawDepth = 0.825f;
enabled = true;
codeBasedBlocks = false;
PlayAnimation("idle");
}
#endregion
#region Public Methods
public override void Update(GameTime gameTime)
{
if (!Dead)
{
string newAnimation = "idle";
velocity = new Vector2(0, velocity.Y);
GamePadState gamePad = GamePad.GetState(PlayerIndex.One);
KeyboardState keyState = Keyboard.GetState();
if (keyState.IsKeyDown(Keys.Left) ||
(gamePad.ThumbSticks.Left.X < -0.3f))
{
flipped = false;
newAnimation = "run";
velocity = new Vector2(-moveScale, velocity.Y);
}
if (keyState.IsKeyDown(Keys.Right) ||
(gamePad.ThumbSticks.Left.X > 0.3f))
{
flipped = true;
newAnimation = "run";
velocity = new Vector2(moveScale, velocity.Y);
}
if (newAnimation != currentAnimation)
{
PlayAnimation(newAnimation);
}
if (keyState.IsKeyDown(Keys.Space) ||
(gamePad.Buttons.A == ButtonState.Pressed))
{
if (onGround)
{
Jump();
newAnimation = "jump";
}
}
if (currentAnimation == "jump")
newAnimation = "jump";
if (keyState.IsKeyDown(Keys.Up) ||
gamePad.ThumbSticks.Left.Y > 0.3f)
{
checkLevelTransition();
}
}
velocity += fallSpeed;
repositionCamera();
base.Update(gameTime);
}
public void Jump()
{
velocity.Y = -500;
}
#endregion
#region Helper Methods
private void repositionCamera()
{
int screenLocX = (int)Camera.WorldToScreen(worldLocation).X;
if (screenLocX > 500)
{
Camera.Move(new Vector2(screenLocX - 500, 0));
}
if (screenLocX < 200)
{
Camera.Move(new Vector2(screenLocX - 200, 0));
}
}
private void checkLevelTransition()
{
Vector2 centerCell = TileMap.GetCellByPixel(WorldCenter);
if (TileMap.CellCodeValue(centerCell).StartsWith("T_"))
{
string[] code = TileMap.CellCodeValue(centerCell).Split('_');
if (code.Length != 4)
return;
LevelManager.LoadLevel(int.Parse(code[1]));
WorldLocation = new Vector2(
int.Parse(code[2]) * TileMap.TileWidth,
int.Parse(code[3]) * TileMap.TileHeight);
LevelManager.RespawnLocation = WorldLocation;
velocity = Vector2.Zero;
}
}
#endregion
}
}
I have figured out for my self, I mostly wanted a quick answer. Just making a public vector does not help, I needed a method to transfer over the Vector:
public Vector2 Velocitys
{
get { return velocity; }
set { velocity = value; }
}
Then just like the public int Score method I draw it:
spriteBatch.DrawString(
pericles8,
"Velocity: " + player.Velocitys.ToString(),
Velocitys,
Color.White);
It works like a charm.
(Its pretty Ironic that the one thing that I asked why I would use it (get and set) would be the answer)

Why won't my sprite draw? (XNA)

I was just messing around with XNA and trying to get a simple player class that could move around through keyboard controls. I can't seem to get it to draw the way I have it set up now though. I'm not seeing what error I'm making.
Here's the Actor base class:
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace RunnerTEst
{
class Actor
{
public static List<Actor> actors;
public Texture2D texture;
protected Vector2 position;
protected float rotation;
protected float scale;
protected Color color;
#region Constructors
static Actor()
{
actors = new List<Actor>();
}
public Actor(Texture2D texture)
{
actors.Add(this);
this.texture = texture;
this.position = Vector2.Zero;
this.rotation = 0f;
this.scale = 1f;
}
#endregion
#region Properties
public Vector2 Position
{
get { return this.position; }
set { this.position = value; }
}
public Vector2 Origin
{
get { return new Vector2(this.position.X + this.texture.Width / 2,
this.position.Y + this.texture.Height / 2); }
}
public float Rotation
{
get { return this.rotation; }
set { this.rotation = value; }
}
public float Scale
{
get { return this.scale; }
set { this.scale = value; }
}
public Color Color
{
get { return this.color; }
set { this.color = value; }
}
public float Width
{
get { return this.texture.Width; }
}
public float Height
{
get { return this.texture.Height; }
}
#endregion
#region Methods
public virtual void Update(GameTime gameTime)
{
}
public virtual void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(this.texture, this.position, this.color);
}
#endregion
}
}
Player class:
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace RunnerTEst
{
class Player : Actor
{
private const float speed = 5f;
protected Vector2 velocity;
private static KeyboardState currState, prevState;
static Player()
{
currState = prevState = Keyboard.GetState();
}
public Player(Texture2D texture, Vector2 position)
: base(texture)
{
this.position = position;
this.velocity = Vector2.Zero;
}
public override void Update(GameTime gameTime)
{
this.HandleInput();
this.position += this.velocity;
foreach (Actor actor in Actor.actors)
{
if (this == actor)
continue;
this.CheckCollision(actor);
}
base.Update(gameTime);
}
public override void Draw(SpriteBatch spriteBatch)
{
base.Draw(spriteBatch);
}
public void CheckCollision(Actor actor)
{
//--left/right sides
if (this.position.X + this.Width > actor.Position.X) //right of this hitting left actor
{
this.position.X = actor.Position.X - this.Width;
}
else if (this.position.X < (actor.Position.X + actor.Width))//left this hit right actor
{
this.position.X = actor.Position.X + actor.Width;
}
//--top/bottom
if (this.position.Y + this.Height > actor.Position.Y) //this bottom hit actor top
{
this.position.Y = actor.Position.Y - this.Width;
}
else if (this.position.Y < (actor.Position.Y + actor.Height))//this top hit actor bottom
{
this.position.Y = actor.Position.Y + actor.Height;
}
//TODO: check screen bounds
}
public void HandleInput()
{
currState = Keyboard.GetState();
if (currState.IsKeyDown(Keys.W))
{
this.velocity.Y = -speed;
}
else if (currState.IsKeyDown(Keys.S))
{
this.velocity.Y = speed;
}
else
{
this.velocity.Y = 0f;
}
if (currState.IsKeyDown(Keys.A))
{
this.velocity.X = -speed;
}
else if (currState.IsKeyDown(Keys.D))
{
this.velocity.X = speed;
}
else
{
this.velocity.X = 0f;
}
prevState = currState;
}
}
}
and lastly, the game:
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 RunnerTEst
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D playerTexture;
Player me;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
playerTexture = Content.Load<Texture2D>(#"Textures\player");
me = new Player(playerTexture, new Vector2(200, 200));
}
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();
me.Update(gameTime);
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
me.Draw(spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
Thanks in advance for your time!
I looked through it, and it looks like you never define the Actor's color property. This means that the color variable defaults to black, which means that the tint given to the Draw line (spriteBatch.Draw(this.texture, this.position, this.color);) is Black, which hides the sprite.
Just set the color of the Actor to white somewhere (I just set it underneath me = new Player(playerTexture, new Vector2(200, 200));).
So the new LoadContent would look like:
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
playerTexture = Content.Load<Texture2D>(#"Textures\player");
me = new Player(playerTexture, new Vector2(200, 200));
me.Color = Color.White;
}
Hope that helps,
max

Categories

Resources