How to take damage from enemies (bullets) - xna

Hello fellow programmers! I am sorry to bother you, but I have a school project which is to create a game. I am almost finish all I have to do is to make my character (player) take damage from the enemy bullets.
Here is my enemy class where I have my bullet list which makes the enemies shoot bullets. You can see that Ive tried to track the position of the bullets by temp.(I followed these tutorials on making the enemies https://www.youtube.com/watch?v=_TlnUM-uhSI and https://www.youtube.com/watch?v=tfiKwOo_4xo)
Before you jump on me I just wanna say I have searched everywhere for an answer but since XNA is very limited on what I wanna create it makes it very hard for me.
class Enemies
{
public Texture2D texture;
public Vector2 position;
public Vector2 velocity;
public bool isVisible = true;
Random random = new Random();
int randX, randY;
float temp_bulletenemyX;
float temp_bulletenemyY;
// bullets
private List<Bullets> bullets = new List<Bullets>();
Texture2D bulletTexture;
public Enemies(Texture2D NewTexture, Vector2 NewPosition, Texture2D newBulletTexture)
{
texture = NewTexture;
position = NewPosition;
randY = random.Next(-4, 4);
randX = random.Next(-4, -1);
velocity = new Vector2(randX, randY);
bulletTexture = newBulletTexture;
}
float shoot = 0;
public void update(GraphicsDevice graphics, GameTime gameTime)
{
KeyboardState keyboardState = Keyboard.GetState();
position += velocity;
if (position.Y <= 0 || position.Y >= graphics.Viewport.Height - texture.Height)
velocity.Y = -velocity.Y;
if (position.X < 0 - texture.Width)
isVisible = false;
shoot += (float)gameTime.ElapsedGameTime.TotalSeconds;
if (shoot > 1)
{
shoot = 0;
Shootbullet();
}
updateBullets();
}
public void updateBullets()
{
foreach (Bullets bullet in bullets)
{
bullet.position += bullet.velocity;
temp_bulletenemyX = bullet.position.X;
temp_bulletenemyY = bullet.position.Y;
if (bullet.position.X < 0)
bullet.isVisible = false;
}
for (int i = 0; i < bullets.Count; i++)
if(!bullets[i].isVisible)
{
bullets.RemoveAt(i);
i--;
}
}
public void Shootbullet()
{
Bullets newBullet = new Bullets(bulletTexture);
newBullet.velocity.X = velocity.X - 3f;
newBullet.position = new Vector2(position.X + newBullet.velocity.X, position.Y + (texture.Height / 2) - (bulletTexture.Height / 2));
newBullet.isVisible = true;
if (bullets.Count() < 3) // hur många skott den skall skjuta
bullets.Add(newBullet);
}
public void draw(SpriteBatch spriteBatch)
{
foreach (Bullets bullet in bullets)
bullet.Draw(spriteBatch);
spriteBatch.Draw(texture, position, Color.White);
}
public float PosX
{
get
{
return position.X;
}
}
public Vector2 Pos
{
get
{
return position;
}
}
public float PosY
{
get
{
return position.Y;
}
}
public List<Bullets> GetbulletList
{
get{
return bullets;
}
}
public Texture2D text
{
get
{
return texture;
}
}
public Texture2D BulletText
{
get
{
return bulletTexture;
}
heres the fundamental Game1 code which I have tried to make so my character can take damage.
player.rectangle = new Rectangle(Convert.ToInt32(player.PosX), Convert.ToInt32(player.PosY), player.text.Width, player.text.Height);
foreach (Enemies bullet in enemies.ToList())
{
rec_bullet = new Rectangle(Convert.ToInt32(bullet.GetbulletList.ElementAt(i).position.X), Convert.ToInt32(bullet.GetbulletList.ElementAt(i).position.Y), nyenemy.BulletText.Width, nyenemy.BulletText.Height);
hit = CheckCollision(rec_bullet, player.rectangle);
if (hit == true)
{
player.health -= 10;
hit = false;
}
i++;
I am very sorry if everything is a mess, Ive have put everything together through following many tutorials and some of my own coding. I am also very sorry if I am violating forum rules, I am new here.
Best Regards Kiar.

I'm going to be brave and suggest the following - looking at the snippets of code supplied.
In Game1 code - you are working you way through the enemies, however it looks like you are not searching through the list of bullets for each enemy. You are getting the ElementAt(..) with 'i' - adding one to it, then going to the next enemy and then only getting the ElementAt(..) with the incremented 'i'.
From my understanding - the flow of the code should be:
for each enemy in enemy list
for each bullet in enemy bullet list
Check Collision with Player
if collision then adjust player health

There are a few things wrong with your code. For starters, your Bullet class should contain the bulletUpdate() method, which should be called in a foreach loop.
foreach (Bullet b in bullets)
{
b.update(/*parameters here*/);
}
Your bullets List should be a public list stored in your Game1.cs or an EnemyManager class, not in each enemy. Pass each enemy a reference to that list, so that when they fire, they can add the bullet to the list.
On top of that, your collision test should be nothing more than an Intersection test between each bullet and yourself. Again, another foreach loop.
foreach(Bullet b in bullets)
{
//where playerRect is the hitbox for your player and b.Rect is the hitbox for your bullet
if(playerRect.Intersects(b.Rect)
player.healh-=damage;
}
Hope that helps.

Related

Dart StageXL activate mouse event on overlapping sprites

Is it possible to have a mouse event be called for two sprites overlapping? I have attempted to use getObjectsUnderPoint however it does not seem to be working.
class Line extends Sprite
{
int x;
int y;
int type;
var tempLine = new Shape();
bool isClicked = false;
Line(int xPos, int yPos, int type)
{
this.x = xPos;
this.y = yPos;
this.type = type;
if(type == 1)
{
graphics.beginPath();
graphics.moveTo(x, y);
graphics.lineTo(x+300, y);
graphics.closePath();
graphics.strokeColor(Color.LightGray,19);
addEventListener(MouseEvent.CLICK, react);
tempLine.graphics.beginPath();
tempLine.moveTo(x,y);
tempLine.graphics.lineTo(x+300,y);
tempLine.graphics.closePath();
}
else if(type == 2)
{
graphics.beginPath();
graphics.moveTo(x, y);
graphics.lineTo(x, y+300);
graphics.closePath();
graphics.strokeColor(Color.LightGray,19);
addEventListener(MouseEvent.CLICK, react);
tempLine.graphics.beginPath();
tempLine.moveTo(x,y);
tempLine.graphics.lineTo(x,y+300);
tempLine.graphics.closePath();
}
addChild(tempLine);
}
react(MouseEvent event)
{
Point tempPoint = new Point(event.localX, event.localY);
graphics.strokeColor(Color.Black,19);
isClicked = true;
var subShape = getObjectsUnderPoint(tempPoint);
for(Shape i in subShape)
{
i.parent.userData.isClicked = true;
}
}
}
I have two Line objects overlapping and when one is clicked I want the boolean for both objects to be true. I have read that the getObjectsUnderPoint does not return a Sprite, could this be the issue?
MouseEvents are only dispatched to the top most display object that extends the InteractiveObject class (which is true for all DisplayObjectContainers and Sprites). So only one display object can receive the MouseEvent.CLICK event. You are right that the getObjectsUnderPoint does only return the children of DisplayObjectContainers but there is an open issue on the GitHub repository (https://github.com/bp74/StageXL/issues/209) talking about this. One of the next versions of StageXL (greater than version 0.13) may change this behavior.

Dart StageXL sprite color change on mouse click

I am relatively new to both StageXL and Dart and I am having difficulty changing the color of a Sprite on a mouse click. Currently I am just referencing the sprite and calling the graphics fillColor() method however nothing changes. Any ideas on how to change individual Sprite lines by mouse click?
class GameBoard
{
Stage stage;
int xPos;
int yPos;
var circle;
var line;
GameBoard(Stage s)
{
this.stage = s;
this.xPos = 100;
this.yPos = 100;
this.circle = new Sprite();
this.line = new Sprite();
}
Sprite generateDots(int x, int y, int size)
{
circle.graphics.circle(x,y,size);
circle.graphics.fillColor(Color.Black);
circle.addEventListener(MouseEvent.CLICK, reactCircle);
return circle;
}
Sprite generateHorzLines(int x, int y)
{
line.graphics.beginPath();
line.graphics.moveTo(x, y);
line.graphics.lineTo(x+100, y);
line.graphics.closePath();
line.graphics.strokeColor(Color.Gray);
line.addEventListener(MouseEvent.CLICK, reactHorzLine);
return line;
}
Sprite generateVertLines(int x, int y)
{
line.graphics.beginPath();
line.graphics.moveTo(x, y);
line.graphics.lineTo(x, y+100);
// this.line.graphics.closePath();
line.graphics.strokeColor(Color.Gray);
line.addEventListener(MouseEvent.CLICK, reactVertLine);
return line;
}
void generateBoard()
{
for(int i = 0; i < 5;i++)
{
for(int j = 0; j< 5;j++)
{
//render horizontal lines
if(j < 4)
{
stage.addChild(generateHorzLines(xPos,yPos));
}
//render vertical lines
if(i<4)
{
stage.addChild(generateVertLines(xPos,yPos));
}
//render points
stage.addChild(generateDots(xPos,yPos,5));
xPos+=100;
}
yPos+=100;
xPos = 100;
}
}
void reactHorzLine(MouseEvent event)
{
line.graphics.fillColor(Color.Red);
}
void reactVertLine(MouseEvent event)
{
line.graphics.fillColor(Color.Green);
}
void reactCircle(MouseEvent event)
{
circle.graphics.fillColor(Color.Blue);
}
}
The current version of StageXL (0.12) has no support for vector graphics when using the WebGL renderer only the Canvas2D renderer is supported. This will change with the next versions where vector graphics are also supported with the WebGL renderer. In the meantime you can opt-out of the WebGL renderer to use the Canvas2D renderer.
// do this before you construct the Stage
StageXL.stageOptions.renderEngine = RenderEngine.Canvas2D;
Btw. you will get best performance by using Bitmaps/BitmapDatas in StageXL. They are based on textures which will be rendered much faster than vector graphics.

XNA 4.0 3D Collision

I've been trying to work on a 3d forward-runner game (like temple run) in XNA 4.0.
I'm hitting a bit of a brick wall, so any help would be much appreciated!
Currently, I'm using my own method for collision detection, which requires the dimensions for each model to be hard-coded into the collision method. I've tried using the code from Microsoft, directly below, but it always returns false:
static bool CheckForCollisions(Entity c1, Entity c2)
{
for (int i = 0; i < c1.body.Meshes.Count; i++)
{
// Check whether the bounding boxes of the two cubes intersect.
BoundingSphere c1BoundingSphere = c1.body.Meshes[i].BoundingSphere;
c1BoundingSphere.Center += c1.position;
for (int j = 0; j < c2.body.Meshes.Count; j++)
{
BoundingSphere c2BoundingSphere = c2.body.Meshes[j].BoundingSphere;
c2BoundingSphere.Center += c2.position;
if (c1BoundingSphere.Intersects(c2BoundingSphere))
{
return true;
}
}
}
return false;
}
This was taken and modified very slightly from, Here My Entity class goes as follows.
Code of mine which I think is relevant would be:
public class Entity
{
public int rowID;
public Model body;
public Vector3 position;
public float rotation = 0f;
public float rotatePerFrame = 0f;
protected internal float toRight = 0;
protected internal float toLeft = 0;
protected internal float forward = 0;
protected internal float back = 0;
protected internal float bottom = 0;
protected internal float top = 0;
public void setDimensions(float right, float left, float front, float back, float top, float bottom)
{
this.toRight = right;
this.toLeft = left;
this.forward = front;
this.back = back;
this.top = top;
this.bottom = bottom;
}
public Entity RotateEnt(Entity e,float degrees)//Psuedo-only accurate to 90 degrees.
{
float actual = MathHelper.ToDegrees(degrees);
switch ((int)actual)
{
case 0:
break;
case 90:
// float temp = e.forward;
// e.forward = e.toLeft;
// e.toLeft =e.back ;
// e.back = e.toRight;
// e.toRight = temp;
float temp = e.forward;
e.forward = e.toRight;
e.toRight = e.back;
e.back = e.toLeft;
e.toLeft = temp;
break;
case 180:
e.forward = e.back;
e.back = e.forward;
e.toRight = e.toLeft;
e.toLeft = e.toRight;
break;
default: //case: 270
e.toRight = e.forward;
e.back = e.toRight;
e.toLeft = e.back;
e.forward = e.toLeft;
break;
}
return e;
}
public bool Collides(Entity e)
{
Entity c1 = RotateEnt(this, this.rotation);
Entity c2 = RotateEnt(e, e.rotation);
float myRightest = c1.position.X + c1.toRight;
float myLeftest = c1.position.X - c1.toLeft;
float hisRightest = c2.position.X + c2.toRight;
float hisLeftest = c2.position.X - c2.toLeft;
if(Collides1D(myLeftest, myRightest, hisLeftest, hisRightest))
{
float myTop = c1.position.Y + c1.top;
float myBottom = c1.position.Y - c1.bottom;
float hisTop = c2.position.Y + c2.top;
float hisBottom = c2.position.Y - c2.bottom;
if (Collides1D(myBottom, myTop, hisBottom, hisTop))
{
float myBack = c1.position.Z - c1.forward;
float myForward = c1.position.Z + c1.back;
float hisBack = c2.position.Z - c2.forward;
float hisForward = c2.position.Z + c2.back;
if (Collides1D(myBack, myForward, hisBack, hisForward))
{
return true;
}
}
}
return false;
}
}
static bool Collides1D(float left1, float right1, float left2, float right2)
{
if (left1 >= left2 && left1 <= right2)
return true;
if (right1 >= left2 && right1 <= right2)
return true;
if (left2 >= left1 && left2 <= right1)
return true;
if (right2 >= left1 && right2 <= right1)
return true;
return false;
}
My own method has been screwing up also, when trying to rotate models.
Ideally, it would be good to know what is wrong with the code from Microsoft, so that I can use it wherever, without worrying about hard-coding in object dimensions.
If anyone can see a fast fix to my own basic collision detection method, that would also be great.
I've looked at the Reimers tutorials, but I'm not getting them at the moment, maybe I've been staring at my own code for too long...
Any other information you want, I can try and supply. I can upload the models also, if that's the problem. I'm using models from Maya, exported as FBX.
I'm using MSVS 2010.
Thanks very much!
Jack
I think the problem may not be in the collision code, but in how you are updating the position of your Entitys. I don't see any update code or MoveForward(), etc, type of code. First of all, though, I think it would be much easier for you to use a Matrix instead of a bunch of float values for rotation. For example, you could have:
public class Entity
{
...
public Matrix RotationMatrix = Matrix.Identity;
public Vector3 position;
Public Entity(Vector3 FaceDirection, Vector3 UpDirection, Vector3 Position)
{
...
position = Position
RotationMatrix = Matrix.CreateWorld(Position, FaceDirection, UpDirection)
}
}
Then if you want to rotate, all you have to do is:
public Void RotateEnt(float Degrees)
{
RotationMatrix *= Matrix.CreateFromAxisAngle(RotationMatrix.Up, MathHelper.ToRadians(Degrees));
}
And if you do all this, then you should easily be able to update your Entity's position, which I think is the problem
public Void Update(GameTime gametime)
{
position += RotationMatrix.Forward * gametime.ElapsedRealTime.TotalMilliseconds * x; //x = some number to scale up or down velocity.
}
If you do this, I think your Entity's position will be updated, which then should fix your collision problem. But, not knowing how you update the position of your Entities, I am just speculating. HTH

Making an object appear to move across the screen randomly

I'm currently doing an assignment, on which one of the requirements is for a random object to appear on screen and move across. Being new to XNA, i do not know where to even begin implementing such behaviours to the game, thus would really appreciate if someone could give me a nudge towards the right direction.
I'm only really accustomed to invoking something when a key is pressed, however with something completely random, this can't be done. as far as i am aware of.
Thank you.
You need to create and set up a sprite for the UFO first. In your protected override void Update(GameTime gameTime) code you simply need to get the current time and compare it to the rules in which you wish to apply. Then update if you wish to draw and "move" the sprite. Here is an example:
#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
#endregion
public class Game : Microsoft.Xna.Framework.Game {
#region Game Settings
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
GraphicsDevice device;
int screenWidth = 800;
int screenHeight = 600;
bool fullscreen = false;
string title = "MyGame";
string origionaltitle;
float frames = 0;
float framesPerSecond = 0;
int startTime;
int currentTime;
int nextTime;
#endregion
struct sprite {
public string TextureName;
public Texture2D Texture;
public Vector2 Position;
public Vector2 Speed;
public Color[] TextureData;
};
bool DrawUFO = false;
sprite ufo = new sprite();
public Game() {
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void LoadContent() {
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
device = graphics.GraphicsDevice;
// TODO: use this.Content to load your game content here
ufo.TextureName = "ufo";
ufo.Texture = Content.Load<Texture2D>(ball.TextureName);
ufo.TextureData = new Color[ufo.Texture.Width *ufo.Texture.Height];
ufo.Texture.GetData(ball.TextureData);
}
protected override void Initialize() {
// TODO: Add your initialization logic here
ufo.Position = new Vector2(10f, 10.0f);
ufo.Speed = new Vector2(0.0f, 10.0f);
//
// Set up game window
graphics.PreferredBackBufferWidth = screenWidth;
graphics.PreferredBackBufferHeight = screenHeight;
graphics.IsFullScreen = fullscreen;
graphics.ApplyChanges();
origionaltitle = title;
Window.Title = title;
//
// Set the initial time
startTime = DateTime.Now.Second;
//
// Set "random"/next time for ufo to be rendered
nextTime = startTime + rand.Next(2);
//
base.Initialize();
}
protected override void Update(GameTime gameTime) {
//
// Set the current time
currentTime = DateTime.Now.Second;
//
// if not drawing ufo then
if(!DrawURO) {
//
// check current time and compare it with the next time
if( currentTime == nextTime ) {
DrawURO = true;
}
} else {
//
// Update UFO position (aka move it)
ufo.Posistion += ball.Speed *(float)gameTime.ElapsedGameTime.TotalSeconds;
//
// if ufo goes of the screen then
if(ufo.Position.Y > screenHeight) {
//
// Reset ufo
DrawURO = false;
ufo.Position.X = 10.0f;
ufo.Position.Y = 10.0f;
//
// set next time to render
nextTime = currentTime + rand.Next(2);
}
}
}
protected override void Draw(GameTime gameTime) {
graphics.GraphicsDevice.Clear(Color.Black);
// TODO: Add your drawing code here
spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
if(DrawUFO == true) {
spriteBatch.Draw(ufo.Texture, ufo.Position, Color.White);
}
spriteBatch.End();
//
base.Draw(gameTime);
}
}
I copied this from some code i did at college a few years a ago, so apologies for any bugs.

is it possible to move the map on touch in blackberry by using MapField.

I am using mapField to create a custom map.I am using the code in this link.
How to show more than one location in Blackberry MapField?.
But the map position is fixed. i am not able to drag the map as we can do in google maps or when we invoke the maps like
public void execute(ReadOnlyCommandMetadata metadata, Object context)
{
Invoke.invokeApplication(Invoke.APP_TYPE_MAPS, new MapsArguments());
}
Here's some code that should get you going on the correct path. I've taken it from a project of mine that had some special requirements, so there could be some remnants of that left in there inadvertently. There will be some undefined variables in there -- they're member variables that are declared in the class and should all start with an underscore. This is also part of a class that extends MapField, so you would have to create a custom map class and then use that rather than the default.
protected boolean touchEvent(TouchEvent message) {
boolean ret = super.touchEvent(message);
//mark that we're starting to interact
if(message.getEvent() == TouchEvent.DOWN) {
_startTouchTracking = true;
_clicking = true;
_touchX = message.getX(1);
_touchY = message.getY(1);
}
//user is wanting to move the map
else if(message.getEvent() == TouchEvent.MOVE) {
int dx = _touchX - message.getX(1);
int dy = _touchY - message.getY(1);
_clicking = false;
_touchX = message.getX(1);
_touchY = message.getY(1);
//perform checks to make sure we don't move outside of the map's range
int lat = getLatitude() - dy*(int)MathUtilities.pow(2, (double)getZoom());
if(lat < -9000000) {
lat = -9000000;
}
else if (lat > 9000000) {
lat = 9000000;
}
int lon = getLongitude() + dx*(int)MathUtilities.pow(2, (double)getZoom());
if(lon < -18000000) {
lon = -18000000;
}
else if (lon > 18000000) {
lon = 18000000;
}
moveTo(lat, lon);
}
//if the person just touches and releases, we want to move to that spot
else if (message.getEvent() == TouchEvent.UNCLICK && _clicking) {
int dx = message.getX(1) - getWidth()/2;
int dy = message.getY(1) - getHeight()/2;
move(dx, dy);
_clicking = false;
}
//touch has been released
else if (message.getEvent() == TouchEvent.UP) {
_startTouchTracking = false;
}
//we handled the click
return true;
}
As said, this might need tweaking for your use, but in general should get you started. The MathUtilities.pow() calls were my way of coming up with an appropriate amount of motion depending on the zoom level.
Edit for Comments
Letting a Bitmap move with the map:
protected Coordinates _bitmapCoordinates;
protected Bitmap _bitmap;
public YourMapField() {
//we're going to put the bitmap at -38.43, 20.32
_bitmapCoordinates = new Coordinates(-38.43, 20.32, 0.0);
_bitmap = YOUR_CODE_TO_GET_THE_BITMAP;
}
protected void paint(Graphics g) {
super.paint(g);
XYPoint placeToPaintBitmap = new XYPoint();
convertWorldToField(_bitmapCoordinates, placeToPaintBitmap);
//perform a check here to make sure that field will be seen. This code would depend
//on how you're painting the image. Just check the placeToPaintBitmap.x and placeToPaintBitmap.y
//against 0 and the map's width and height, along with some adjustment for how you paint
if(bitmap will be visible on the screen) {
//The code I have here is drawing the bitmap from the top left of the image, but if
//you need to draw from some other place you may have to offset the x and y
g.drawBitmap(placeToPaintBitmap.x, placeToPaintBitmap.y, _bitmap.getWidth(), _bitmap.getHeight(), 0, 0);
}
}
I didn't test any of that code, so it might be buggy but should give you the general idea.

Resources