I'm coding a game in XNA and I have two subclasses (Character and Enemy). I wanted to create a method that would lower an enemy's health by the character attack score. How would I do that? I'm having issues with having classes interact with each other.
Would it be possible to do something similar to a constructor, where I could type in something like:
Attack(player.attack, enemy.health);
And if the player's attack score was 2, and the enemies health was 10, after invoking the method the enemy would have 8 health left.
Probably cleaner to make Attack a method on the enemy class, then you can Attack the enemy using your player:
enemy.Attack(player);
The code in the Attack method on the enemy will look at the player.attack property, and decrement its own health accordingly.
You might consider splitting this up a little. Example:
// Method on each player, which in turn calls the method below.
// This is called when myPlayer attacks enemyPlayer.
myPlayer.AttackPlayer(enemyPlayer);
// Called from within the AttackPlayer method which was called on
// myPlayer. The parameter <damage> is a (private?) property in myPlayer:
enemyPlayer.ReceiveAttack(damage);
This should make it fairly clear what is happening, and let you handle different aspects in a flexible way, in case you might want to expand this later.
Example: The player receiving the attack might behave differently in different situation (eg. receive less damage if he has armour, etc), without the attacker having to take this into consideration.
Related
I watched Basic Platformer Game tutorial for Unity where presenter created coin pick-up script that he attached to Coin prefab. I want to know if the pick-up script should be attached to the Player or Coin GameObject.
Let's say we have a game with pick-upable objects. They do nothing more than incrementing the score (or affecting the player in another way) and destroy themselves on collision.
I was wondering that what is the preferred approach to this problem.
I've come up with two approaches:
Approach A
Have one ObjectPickup script on the player game object. This script would do whatever is required depending on the type of collided object.
private void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.CompareTag("Coin"))
{
IncrementScore();
Destroy(other.gameObject);
}
else if (other.gameObject.CompareTag("SuperSpeed"))
{
IncreasePlayerSpeed();
Destroy(other.gameObject);
}
}
Approach B
Have CoinPickup script on every coin and SuperSpeedPickup script on every super speed powerup.
private void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.CompareTag("Player"))
{
other.gameObject.IncrementScore();
Destroy(gameObject);
}
}
And other script:
private void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.CompareTag("Player"))
{
other.gameObject.IncreasePlayerSpeed();
Destroy(gameObject);
}
}
Is Approach A more efficient then Approach B? If so what is the rough number of GameObjects when Approach A becomes preferable?
Or is it always better to work with Approach B as it seems to be cleaner (when we have a number of different pick-upable objects)?
In your example, "approach a" would be more efficient than the other because the OnTriggerEnter2D is called once. With "approach b", OnTriggerEnter2D is called twice on two different scripts. It's slower for Unity to make callback calls let alone on two different scripts + the player. Also, OnTriggerEnter2D is sent to disabled MonoBehaviours which makes "approach a" more efficient choice. The main reason for the slow event call is because the call is made from native C++ side of the code to the Unity's C# API side and this is costly.
Note that it really doesn't matter that much. This is just an attempt to answer your question for which one is more efficient but what you're doing is a micro-optimization.
The thing that should play big role in this decision is the behavior of the coin after the trigger.
If the coins behave the-same then use "approach a" and do the detection on the player's side.
If the coins have different behavior like coins with different score values, color and action(animation) when they are collected then do the detection on the coins side and handle each coin. This is the reason why scripts are attached to GameObjects in the first place. You don't need different tags for each different coin. Use enum to distinguish their action in the OnTriggerEnter2D function. It would be awful to use "approach a" to handle this in this case.
Considering you can create a prefab for every coin and for every super speed power up with the second approach script already attached to it AND considering you can spawn them very easily from anywhere in the code I'd really stick to the second approach, making it more sensible, clean and clearly understandable from everyone.
I don't like (and I wouldn't absolutely use) the first approach for this specific purpouse mainly because the OnTriggerEnter2D is very likely to be fired a very large number of times since it's put on the player and the player is moving around colliding with stuff everywhere.
I should use the B, cause it's more like how object-programming works (at least on my head!) even if it's more expensive.
But Method A do not split interactions, so imagine that you can collide with 2 different pickable objects, and you collide with bouth at the same time. If you use Method A, it will use allways the same collision-order, which can be desired or not!
But clearly with Method B you don't really know which object will be picked first (in this concrete case!)
Approach A sounds a bit more performant, also it would work with multiplayer. If you have n players, local or online, you'd need to check the player id on the coin. Otherwise you'd need a lot of tags. No need to do that if the players detect item collisions themselves.
this is a question I've had for a while but never bothered asking.
Imagine I have 2 objects. 1 static, and the other movable (by player).
Where would the collision logic exist for that?
To elaborate; in my state I have a list of Components. These can be NPCs, static objects, the player, and just about everything being
private List<Component> _gameComponents;
If I were to do the check in the Player class, surely the player would need to know of the _gameComponents list, and then I'll do the check as I update so I can change the velocity accordingly.
Is there a standard I'm missing?
EDIT 1: I have just read that I should have a step between update and render for checking all collision. I'll give that a try, and see what happens.
Let every component that can be physically processed inherit from a custom interface like ICollidable.
Store every ICollidable in a List<T> that is separate from your components-list. And every ICollidable that is not static in even a third collection.
Have a third class that just processes the whole physics-part of your game and iterates through the non-statics-list. This way you only update what can be moved and you can compare it to every object that is in the list that contains every ICollidable.
Make sure you only check collision for objectes that are within the range of a moving object. It makes no sense to check a collision for an object that won't collide.
I always check for collisions before update, try what works best for you.
I'm working on a 2D platformer in c#, as most people are, but I have got a decent start to the project I have a class called Player, I then handle all collision for that player as well as the scrolling of the blocks in the background within the gamescreen class. I have just added another player (as a different class in this case a warrior), but all of my collision is based around the players positions and velocity, how would I change the blocks movement and collision to be around the warrior's velocity and positions instead (without duplicating or creating quite a lot of code).
Thanks for any help Sam.
Inheritance is your friend. You should probably have a base Player class, or even something more low level than that. The base class implements the colision detection and movement code. Your Warrior and other player types should inherit that class and override different parts to change the behavior.
My strategy works approximately like this:
I have a Character class. It contains a HitboxSet. The HitboxSet exposes an active Hitbox. All my collision is done based on Hitbox instances. Depending on what kind of character I need, I pass in different sprites, hitboxes, movements, etc.
The result is a high degree of flexibility, while allowing you to keep your concerns thoroughly separated. This strategy is known as Composition, and is widely considered superior to inheritance based strategies in almost all cases.
The main advantage of this strategy over inheritance is the ability to mix and match components. If, one day, you decide that you need a new projectile that's smaller than a previous one, and moves in a sine pattern, you simply use a new sine movement. You can reuse such things infinitely, in any combination.
You can do something like this with inheritance: a child class can override a method and do something differently. The problem is that you either keep adding new child classes with different combinations and end up with a terrifyingly complex tree, or you limit your options.
In short, if something is naturally going to vary, as it almost certainly will in a game, those variations should be distinct classes that can be combined in different ways rather than mutually exclusive overrides.
I'm attempting to simulate a ship/space station with internal gravity.
To accomplish this, I'm making the player and all contents of the ship children of the ship. The ship itself has colliders, but no rigid body components. The idea is that as the ship moves, so will all of its contents. Pretty straightforward so far.
To simulate gravity in the ship, the player controller and all rigid bodies have the default gravity turned off. Instead of the standard, each frame a force is applied along the negative up vector of the parent ship.
This sort of works, but there is one major problem that I have to sort out before this thing is solid. All rigid bodies slide around the interior of the ship very slowly.
I'm aware that this is probably due to the updated position of the floor combined with the gravity force resulting in some kind of shear force. The objects always slide against the rotation of the ship.
I've tried mucking around with all of the physics properties from Physic materials to drag to mass, etc. None of these have worked, and I'm pretty sure it's due to the fundamental fact that the floor is moving, even though the RBs are children of the object that the floor is a part of.
Anyone have a solution to this that isn't some kind of duct tape? I could try to make everything kinematic and only "wake up" when certain external collisions occur or something, but that could get very cumbersome. I need for this to work in as much of a general purpose way as possible.
Some code:
On the ship
void Update ()
{
transform.Rotate(new Vector3(Time.deltaTime * 0.125f,Time.deltaTime*0.5f,0));
}
void FixedUpdate()
{
Vector3 tempVec;
foreach(Rigidbody rb in rigidBodies)
{
//Gravity!!
tempVec = transform.up * -9.81f * rb.mass * Time.deltaTime;
rb.AddForce(tempVec, ForceMode.Acceleration);
}
}
I've also worked on a version where the ship was following the movements of a rigid body. I couldn't do direct parenting, so I had to simply set the transform manually each frame to match the physics proxy. This still had the same effect as above, though it's probably ultimately how I want to move the ship, since that will tie into the flight mechanics more properly.
If you equate this to a real world scenario, the only thing that stops us from sliding around on the floor is friction.
Does the Physics library correctly apply friction based on the contacting materials? If not applying a certain amount of friction (or a minimum amount of force applied required to overcome it) should have the effect of preventing you from sliding around on the floor.
Although this is pretty much "duct tape" as above, it could neatly fit in and expand your physics engine if it doesn't already contain a way to enforce it.
As suggested above, the issue is because of how the physics engine applies friction. If I'm not mistaken, there will be some other forces acting on objects in a rotating frame (some of which are very unintuitive - check out this video: https://www.youtube.com/watch?v=bJ_seXo-Enc). However, despite all that (plus likely rounding errors arising from the engine itself and the joys of floating-point mathematics), in the real world, static friction is greater than moving (kinetic) friction. I don't think this is often implemented in game physics engines, which is why we so often see "wobbly" near-static objects. Also, you may run into the issue that even if this is implemented, the physics engine may be interpreting two contacting rotating bodies as non-static (even though their contact surfaces are static from a local perspective, the engine may be thinking globally)... [Insert joke about Newton and Einstein arguing].
https://i.stack.imgur.com/AMDr2.gif shows an idealised version of what friction actually looks like in the real world: until you overcome the static friction, nothing moves.
One way you would implement this (if you can access the physics engine that low-level) would be to round all movement forces below a certain threshold to zero - i.e. force < 0.001* is set to 0 (or possibly velocity < 0.001 is set to zero - whichever is easier).
*Some threshold - you'll have to work out what this is.
Otherwise, maybe you could instruct those objects to stop calculating physics and "stick" them to the parent surface, until such time as you want to do something with them? (This is probably a bad solution, but most of the other ideas above rely on hacking the underlying physics code).
I'm trying to make a jumping mechanism in my game which will work something like this:
// velocity.Y is the velocity of the sprite I want to jump
if (keystate.IsKeyDown(Keys.W))
{
velocity.Y = 3 - (time elapsed since start of jump);
}
I thought this might be a simple and elegant solution to making my sprite jump but if it is not possible like this just say so and it's back to the drawing board.
I would suggest not connecting the physics so directly to the player input, it's not a very extendable architecture.
Have an interface which defines physics properties such as velocity which is implemented by your character object. When the player presses the up-key you should check if the player is on the ground, if they are then set their acceleration to move up. Then have a physics system iterate through a list of every object which implements the physics interface applying gravity and other forces before moving the entities around. This way you can use the same physics code for every entity in your game.
I would also suggest not connecting keyboard input directly to the movement of the player. You can have an interface called 'ICharacterController' which defines a 'nextInstruction' method which returns 'CharacterInstructions' which defines various actions characters can take such as jumping and moving, this can be implemented by an input class. Your character class then holds a reference to a CharacterController so it just calls nextInstruction, this way the character can be controlled by Player Input, AI, or through network communication but still share the same behavior as the player.
Game Coding Complete is a brilliant book to read if you're serious about game programming.
I can also recommend Game Engine Architecture
As you're using XNA you should consider using Game Components
XNA doesn't have built-in methods to detect a press vs. a press-and-hold; it is only able to tell you if the key is currently being pressed.
What you need to do, then, is to store two KeyboardState-s, "Old" and "Current". Once you have this, you are able to detect when a keypress starts (old.isKeyDown == false && current.isKeyDown == true; ) and when it ends (old.isKeyDown == true && current.isKeyDown == false;
So once you have this, it's a simple matter to record a "jumpStart" variable based on the GameTime when you detect the keypress, and a "jumpEnd" variable from when you detect the key release.
If you want to base the duration of a jump on the amount of time the key is held down, you may be better served by setting up an upper limit, afterwhich further holding down of the key has no effect.
not if that what you are looking for in another words if the velocity function is executing while you hold the button but ou can use stopwath to measure that
Stopwatch stopWatch = new Stopwatch();
if (keystate.IsKeyDown(Keys.W))
{
velocity.Y = 3 - (time elapsed since start of jump);
stopWatch.Start();
}
if (keystate.IsKeyUp(Keys.W))
{
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
}
more here
http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-2