How do I delete a GameComponent from Game.Components? - xna

Basically my game is to stop the rocks falling from the sky using a plank.
I'm not sure what is not functioning correctly, but here is my code:
In the RockManager class
public void CheckForPlankCollision(Plank plank)
{
foreach (GameComponent component in Game.Components)
{
if (component is FallingRock rock)
{
if (plank.Bounds.Intersects(rock.Bounds))
{
rock.HandleCollision();
Rectangle bounds = rock.Bounds;
}
}
}
}
In the Rocks class
public void HandleCollision()
{
//rockPosition = rockAfterImpactPosition; // I tried to move it offscreen
//rockPosition = Vector2.Zero; //I tried for any reaction
//this.Enabled = false; // tried this
//Game.Components.Remove(this); //tried this
}
I'm also trying to implement a scoring system. (add 1 point if the rock hits the plank, subtract a point if it hits the ground)

Try casting this as an IGameComponent or GameComponent object.
public void HandleCollision()
{
Game.Components.Remove((GameComponent)this);
}
Tell me if this works for you !
EDIT: You might also want to defer the deletion of your game object to later, when it isn't used by the foreach (GameComponent component in Game.Components) loop, which might have a lock on removing elements during that time.

Related

Can't receive value from another class on XNA Framework C#

I have several classes on my project: Game1(main class(default)), Animation and Enemy:
public class Animation
{
public int currentFrameHit;
public Animation ()
{
}
public void Update(GameTime gameTime)
{
timeElapsedHit += gameTime.ElapsedGameTime.Milliseconds;
if (timeElapsedHit > 100)
{
timeElapsedHit = 0;
currentFrameHit = (currentFrameHit + 1) % 9;
}
}
}
How can i get value from variable in Animation class?
In Enemy class i can't receive this value from Animation. I tried that:
Animation animation = new Animation();
Console.WriteLine(animation.currentFrameHit);
But i'm getting null, however in main class Game1 i receive right values with same code.
The problem is that you're making a new Animation() without assigning it to anything. so it'll keep returning it's default value.
So far there isn't enough information given on what the number should be though. Do you have the Animation() class inside the Enemy Class, or do you find the Enemy Class within Animation()?
You need to reference to an existing animation value.
Create an instance in your desire class (here it is Game1) and don't forget to make it public.
public static Animation animationGame1 = new Animation();
Then in your second class:
In LoadContent(): reference it to Game1's variable:
Animation animationNewClass = Game1.animationGame1;
In Update(): do what you want to achieve:
Console.WriteLine(animationNewClass.currentFrameHit);
Hope this helps.

XNA game frozen

I was following a tutorial for creating a 2d space shooter. It was working fine until I added code to spawn enemy mobs, now it just runs but it's frozen. I can't understand why it wont work. there are no errors anywhere or anything like that.
Thanks.
You have a minor typo with the brackets in your update method.
protected override void Update(GameTime gameTime)
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
//updating mobs and checking for collisions
foreach (Mobs M in mobsList)
{
// Updating the mobs, collision checking, etc here
...
...
Player.update(gameTime);
bG.update(gameTime);
loadAsteroids();
loadMobs();
foreach (Roids R in asteroidList)
{
// Updating the asteroids, collision checking, etc
...
...
M.update(gameTime);
R.update(gameTime);
}
base.Update(gameTime);
}
}
There are two main things wrong in this. Firstly, this bit of code:
Player.update(gameTime);
bG.update(gameTime);
loadAsteroids();
loadMobs();
foreach (Roids R in asteroidList)
{
// Updating the asteroids, collision checking, etc
...
M.update(gameTime);
R.update(gameTime);
}
base.Update(gameTime);
Will be run inside the first foreach loop. You are updating the player, the background, every asteroid, and the window once for each mob, every time you call update. This is only meant to happen once per update, not once per mob that is being updated. This is why your gaming is lagging or freezing. This is just a misplacement of the bracket on the mob's foreach loop - shift all this stuff outside the foreach loop.
The other thing wrong is this part:
foreach (Roids R in asteroidList)
{
// Updating the asteroids, collision checking, etc
...
M.update(gameTime); /* THIS LINE HERE */
R.update(gameTime);
}
Here, you are updating each Mob member once per asteroid. If you have 15 asteroids on screen, each mob member will be updated 15 times. Shift that line up into the first foreach loop.

How to toggle a Key Press

I have the issue. I have programmed my Shoot em up and i came to dead end when i have to ask so many questions in here
if(key State.IsKeyDown(Keys.Space))
{
Shoot Bullets();
}
Problem is when i Hold Space bar it shoots....i do not want to hold Space bar for 30 minutes just to end the level. I wanna make it to toggle.
What is best and least coded way to do it.
I did spend like 2 days trying to figure this out and i can't...help would be appreciated
As #folkol suggested:
Include:
bool Shoot;
And initialize as:
Shoot = false;
What you check for input
if(key State.IsKeyDown(Keys.Space)) // Need to flip on key release
Shoot = !Shoot // Flips the variable
And in your Update() Method:
if(Shoot)
Shoot Bullets(); // Shoots
Notice that this will flip the Shoot Variable a lot. You will need to create an oldState value and flip on key release.
Instead of "Shoot Bullets", flip the value of a boolean variable. And use that variable as the indicated for whether you should fire some bullets in any given game loop iteration.
Something like this:
public class MyGame : Microsoft.Xna.Framework.Game
{
/* Some other state */
bool isShooting = false;
/* Some other methods */
protected override void Update(GameTime gameTime)
{
/* Some other code */
if(keyState.IsKeyDown(Keys.Space))
{
// Flip the boolean value. If it was failse, set it to and vice versa
isShooting = !isShooting; true.
}
if(isShooting)
{
Shoot.Bullets();
}
}
}
I added another short but correct example for you, some of the other answers were pretty much there, but had some errors in them.
KeyboardState kbState;
bool isShooting;
protected override void Update(GameTime gameTime)
{
KeyboardState lastkbState = kbState;
kbState = Keyboard.GetState();
if (kbState.IsKeyDown(Keys.Space) && lastkbState.IsKeyUp(Keys.Space))
{
isShooting = !isShooting;
}
if (isShooting)
{
Shoot.Bullets();
}
}
Your other answer I don't have the reptuation to add a comment on doesn't work because you made the previous and the current keyboard state properties equal the same thing.

Actionscript 2 Proper way to define function on MovieClip

I'm trying to write a function on a MovieClip, and call it from the root clip. What works fine in ActionScript 3 doesn't seem to be working properly in ActionScript 2.
Frame 1 of the _root MovieClip:
var newMovieClip:MovieClip = _root.attachMovie('Notification', id, 0);
newMovieClip.SetNotificationText("Test text");
Frame 1 of the Notification MovieClip:
function SetNotificationText(inputText : String){
notificationText.text = inputText;
}
The result is that the MovieClip is created but the text is not changed.
Am I doing this wrong?
To add functions to a MovieClip in AS2, you need to use one of these methods:
Add the method to the prototype of MovieClip:
MovieClip.prototype.SetNotificationText = function(inputText:String):Void
{
if(this["notificationText"] !== undefined)
{
// If we're going to use the prototype, at least do some checks
// to make sure the caller MovieClip has the text field we expect.
this.notificationText.text = inputText;
}
}
newMovieClip.SetNotificationText("Test text");
Make the MovieClip and argument of the function:
function SetNotificationText(mc:MovieClip, inputText:String):Void
{
mc.notificationText.text = inputText;
}
SetNotificationText(newMovieClip, "Test text");
Add the method directly to the newly created MovieClip:
var newMovieClip:MovieClip = _root.attachMovie('Notification', id, 0);
newMovieClip.SetNotificationText(inputText:String):Void
{
notificationText.text = inputText;
}
newMovieClip.SetNotificationText("Test text");
Option 2 is best overall - it's the cleanest and avoids overhead of creating a new function for every new MovieClip. It also avoids messing around with the prototype, which at best should be used to add generic methods, like a removeItem() method on Array.

Actionscript, objects and event listeners

Say I have an object
var my_obj = new Object();
my_obj['key'] = value;
Is there a way to add an event listener to the value, like
my_obj['key'].addEventListener(Blah Blah);
I have a long(ish) list of buttons on the timeline (the layout is so different from section to section that just makes more sense to do on the timeline rather than trying to build the layouts via actionscript).
button1 = plays "frame label 1"
button2 = plays "frame label 2"
and so on....so I was just thinking of storing everything in an array
obj["button1"] = "framelabel1"
arr.push(obj);
Then I could just have one event handler for all of the buttons and use target to get the frame label value...
Yes, you can do exactly what you're asking in the exact way you've mentioned, here's an example:
var value:Sprite = new Sprite();
var my_obj = new Object();
my_obj['key'] = value;
So calling:
my_obj['key'].addEventListener(Event.ENTER_FRAME, _onEnterFrameHandler);
is exactly the same as calling:
value.addEventListener(Event.ENTER_FRAME, _onEnterFrameHandler);
If the value is an IEventDispatcher or extends EventDispatcher you can add a listener to it.
The question is rather obscure to me. My guess is that you need something triggered every time a value is set. If this is the case, then you have to create a custom class, and declare a getter-setter property there.
For instance:
package
{
import flash.display.Sprite;
public class TestAccessor extends Sprite
{
private var someVarValue:uint = 0;
public function TestAccessor()
{
super();
}
public function get someVar():uint
{
return someVarValue;
}
public function set someVar(value:uint):*
{
someVarValue = value;
// this is the place where someVar is set.
// do whatever else you like here,
// you may choose to dispatch an event from here if you need.
}
}
}
Back in AS1-AS2 era we had watch() and addProperty() for that purpose, but these times are long since gone. For good. :)

Resources