Multi Direction Bullets[read] - c#

Been trying to code something for a while for a project im still working on for school, even though it's done.
I want to make a grenade that shoots out bullets on enemies colliding with it, but what I need help with atm is making 8 bullets shoots in all different directions at once.
here's the code my teacher gave me to do it(I asked him for help)
if (mouse.LeftButton == ButtonState.Pressed)
{
Texture2D pewTexture;
pewTexture = game.Content.Load<Texture2D>("pew");
game.firingSound.Play();
//Tweak pews to shoot at mouse, rather than just going straight on the y axis.
pew = new CPew(game, pewTexture);
pew.velocity = new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation)) * 10f + spriteVelocity;
pew.position = position + pew.velocity * 5;
//easy cheesy way:
//pew.position = position;
//pew.position.X += 15f;
//pew.position.Y -= 20f;
//super awesome cool way for cool people and celebrities
pew.position = position +
new Vector2(
texture.Width * .2f - pew.texture.Width * .2f,
-pew.texture.Height);
game.pews.Add(pew);
myFiringDelay = 10;
}
else
{
if (mouse.RightButton == ButtonState.Pressed)
{
float pi2 = (float)Math.PI * 2.0f;
int numShots = 10;
float pi2overnum = pi2 / numShots;
for (int i = 0; i < numShots; i++)
{
Vector2 direction = PiToVec2(pi2overnum * i);
//particles[i].reset(position,direction, vector2.zero, 6);
game.pews[i].Reset(pew.position, direction, Vector2.Zero);
}
Vector2 PiToVec2(float piT)
{
return new Vector2((float)Math.Sin(piT), (float)Math.Cos(piT));
}
apparently this will make it shoot in every direction on mouse right click but every time I try it and my game crashes straight up
Then we have a pew class which is bullets and thats what I want to be shot in those directions at the same time
you guys may not be able to help with the code i've shown you, i've spent a while looking for a way to do this but i can't seem to find anything
A former example and or source code would be really helpful, just at least another way to look at this thanks.
Showingme when it crashed, it tells me index goes out of range or is negative, if you guys could just show me base code for multidirectional bullets id be happy

The problem your having is that when you try and loop through your game.pews collection you are trying to call Reset() on the first 10 items in the collection. However there appear to not be 10 pews in there. So when you get to the end and try to access the next one, that's where you get the "Index out of range" error.
For your 8 bullets from a grenade part of the question, I think you want to do something like this.
//Once a grenade has collided with an enemy
float pi2 = (float)Math.PI * 2.0f;
int numShots = 8;
float pi2overnum = pi2 / numShots;
for (int i = 0; i < numShots; i++)
{
Vector2 direction = PiToVec2(pi2overnum * i);
pew = new CPew(game, pewTexture);
pew.velocity = new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation)) * 10f + spriteVelocity;
//Set the position based off of the grenades last position.
//Set the direction.
//Set any other attributes needed.
game.pews.Add(pew);
}
Now you have eight bullets moving in different directions from where the grenade exploded.
To update them and draw them I would recommend using a foreach loop so you don't have to worry about "Index out of range" errors.
foreach CPew pew in game.pews
{
pew.Update();
}

Related

How do I make a vector slowly become another?

I am making 2D unity code where I put a random x value and get a gameobject to slowly move to that position. I cant use += or -= because the number can be larger or smaller than the vector. how do I fix this? here is the code.
public IEnumerator fistthrust()
{
float leftpos = Random.Range(-8, 8);
float rightpos = Random.Range(-8, 8);
while (fist.transform.position.x != leftpos && rightfist.transform.position.x != rightpos)
{
fist.transform.position = new Vector3(leftpos, 0, 0); -- fix these
rightfist.transform.position = new Vector3(rightpos, 0, 0); -- 2 lines
}
fistscr.down();
yield return new WaitForSeconds(0.5f);
rfistscr.down();
fistscr.up();
yield return new WaitForSeconds(0.5f);
rfistscr.up();
fistscr.rest();
yield return new WaitForSeconds(0.5f);
rfistscr.rest();
}
I am a beginner game designer and have no idea what to try or what to do. Please help!!
Looks like theres a MoveTowards function in the Vector3 Object https://docs.unity3d.com/ScriptReference/Vector3.MoveTowards.html That should do what you want.
So something like
Vector3 currentPosition = ...;
Vector3 targetPosition = ...;
// Use Vector3.MoveTowards to move towards the target
currentPosition = Vector3.MoveTowards(currentPosition, targetPosition, 3 * Time.deltaTime);
Would move the currentPosition 3 steps towards the target position.
Then you can simply add this in a while loop or something to move it smoothly over time

How to calculate position of edge circle and rotation to center

i have mathematical formula and i have spawn points. but, i have so differenet object sizes and radiuses. how i can instantiate a objects in the edge of circle and rotate them onto center circle like picture;
i am bad with this stuf and my code is wrong or not i dont know
```
public void GetObstacle(int count, CircleRotator rotator)
{
float TAU = 6.283185307179586f;
for (int i = 0; i < count; i++)
{
Transform cameraTR = mainCamera.transform;
Transform tr = rotator.transform;
var obj = new GameObject();
float t = (float)i / count;
float angle = t * TAU * 0.25f; //
Vector3 itemCenter = new Vector3(Mathf.Cos(angle) * rotator.GetRadius + tr.position.x,
tr.position.y + Mathf.Sin(angle) * rotator.GetRadius);
obj.transform.position = itemCenter;
Vector3 current = tr.position - cameraTR.position;
Vector3 target = obj.transform.position - cameraTR.position;
obj.transform.Rotate(Vector3.forward, Vector3.Dot(current, target));
obj.transform.SetParent(tr);
}
}
```
where 0.25 in here i dont understand. But without 0.25 all will broke. angle = t * TAU * 0.25f;
help pls or give some adwice. https://ibb.co/qNhZCh3 what i would like but what i have https://ibb.co/NFSRmSn
so many formulas and watched videos. but i can't understand how
Thanks #Ruzihm with help rotations.
spawn outside edge I got this way, where I'm not sure if this is the right way, where Size is the size of y collider. If someone show another good way i will be gratitude!
Vector3 direction = (tr.position - obj.transform.position);
obj.transform.rotation = Quaternion.LookRotation(Vector3.forward, direction);
obj.transform.position -= direction.normalized * obj.Size()/2f;

2D Projectile Trajectory Prediction(unity 2D)

using (unity 2019.3.7f1) 2d.
I have a player that moves around using a pullback mechanic and has a max power(like in Angry Birds).
I'm trying to draw a line(using a line renderer) that shows the exact path the player will go. I'm trying to make the line curve just like the player's path will. so far I've only managed to make a straight line in a pretty scuffed way.
The known variables are the Jump Power and the player's position, there is no friction. and I believe gravity is a constant(-9.81). Also, I would like to have a variable that allows me to control the line's length. And, if possible, the line will not go through objects and would act as if it has a collider.
// Edit
This is my current code. I changed The function so it would return the list's points because I wanted to be able to access it in Update() so it would only draw while I hold my mouse button.
My problem is that the trajectory line doesn't seem to curve, it goes in the right angle but it's straight. the line draws in the right direction and angle, but my initial issue of the line not curving remains unchanged. If you could please come back to me with an answer I would appreciate it.
enter code here
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TrajectoryShower : MonoBehaviour
{
LineRenderer lr;
public int Points;
public GameObject Player;
private float collisionCheckRadius = 0.1f;
public float TimeOfSimulation;
private void Awake()
{
lr = GetComponent<LineRenderer>();
lr.startColor = Color.white;
}
// Update is called once per frame
void Update()
{
if (Input.GetButton("Fire1"))
{
lr.positionCount = SimulateArc().Count;
for (int a = 0; a < lr.positionCount;a++)
{
lr.SetPosition(a, SimulateArc()[a]);
}
}
if (Input.GetButtonUp("Fire1"))
{
lr.positionCount = 0;
}
}
private List<Vector2> SimulateArc()
{
float simulateForDuration = TimeOfSimulation;
float simulationStep = 0.1f;//Will add a point every 0.1 secs.
int steps = (int)(simulateForDuration / simulationStep);
List<Vector2> lineRendererPoints = new List<Vector2>();
Vector2 calculatedPosition;
Vector2 directionVector = Player.GetComponent<DragAndShoot>().Direction;// The direction it should go
Vector2 launchPosition = transform.position;//Position where you launch from
float launchSpeed = 5f;//The initial power applied on the player
for (int i = 0; i < steps; ++i)
{
calculatedPosition = launchPosition + (directionVector * ( launchSpeed * i * simulationStep));
//Calculate gravity
calculatedPosition.y += Physics2D.gravity.y * (i * simulationStep);
lineRendererPoints.Add(calculatedPosition);
if (CheckForCollision(calculatedPosition))//if you hit something
{
break;//stop adding positions
}
}
return lineRendererPoints;
}
private bool CheckForCollision(Vector2 position)
{
Collider2D[] hits = Physics2D.OverlapCircleAll(position, collisionCheckRadius);
if (hits.Length > 0)
{
for (int x = 0;x < hits.Length;x++)
{
if (hits[x].tag != "Player" && hits[x].tag != "Floor")
{
return true;
}
}
}
return false;
}
}
Here's a simple way to visualize this.
To create your line you want a bunch of points.
The points represents the player's positions after being fired after X amount of time.
The position of each point is going to be : DirectionVector * (launch speed * time elapse) + (GravityDirection * time elapse^2)
You can decide in advance how far you pre calculate the points by simulating X duration and choosing the simulation step(calculate a point every X amount of time)
To detect collision each time you calculate a point you can do a small circle cast at that location. If it hits something you can stop add new points.
private float collisionCheckRadius = 0.1f;
private void SimulateArc()
{
float simulateForDuration = 5f;//simulate for 5 secs in the furture
float simulationStep = 0.1f;//Will add a point every 0.1 secs.
int steps = (int)(simulateForDuration/simulationStep);//50 in this example
List<Vector2> lineRendererPoints = new List<Vector2>();
Vector2 calculatedPosition;
Vector2 directionVector = new Vector2(0.5f,0.5f);//You plug you own direction here this is just an example
Vector2 launchPosition = Vector2.zero;//Position where you launch from
float launchSpeed = 10f;//Example speed per secs.
for(int i = 0; i < steps; ++i)
{
calculatedPosition = launchPosition + ( directionVector * (launchSpeed * i * simulationStep));
//Calculate gravity
calculatedPosition.y += Physics2D.gravity.y * ( i * simulationStep) * ( i * simulationStep);
lineRendererPoints.Add(calculatedPosition);
if(CheckForCollision(calculatedPosition))//if you hit something
{
break;//stop adding positions
}
}
//Assign all the positions to the line renderer.
}
private bool CheckForCollision(Vector2 position)
{
Collider2D[] hits = Physics2D.OverlapCircleAll(position, collisionCheckRadius);
if(hits.Length > 0)
{
//We hit something
//check if its a wall or seomthing
//if its a valid hit then return true
return true;
}
return false;
}
This is basically a sum of 2 vectors along the time.
You have your initial position (x0, y0), initial speed vector (x, y) and gravity vector (0, -9.81) being added along the time. You can build a function that gives you the position over time:
f(t) = (x0 + x*t, y0 + y*t - 9.81t²/2)
translating to Unity:
Vector2 positionInTime(float time, Vector2 initialPosition, Vector2 initialSpeed){
return initialPosition +
new Vector2(initialSpeed.x * t, initialSpeed.y * time - 4.905 * (time * time);
}
Now, choose a little delta time, say dt = 0.25.
Time | Position
0) 0.00 | f(0.00) = (x0, y0)
1) 0.25 | f(0.25) = (x1, y1)
2) 0.50 | f(0.50) = (x2, y2)
3) 0.75 | f(0.75) = (x3, y3)
4) 1.00 | f(1.00) = (x4, y4)
... | ...
Over time, you have a lot of points where the line will cross. Choose a time interval (say 3 seconds), evaluate all the points between 0 and 3 seconds (using f) and put your line renderer to cover one by one.
The line renderer have properties like width, width over time, color, etc. This is up to you.

Triangle.NET - How to add vertex to existing triangulation?

I've looked through what seems like every question and resource there is for Triangle.NET trying to find an answer to how to insert a vertex into an existing triangulation. The closest I've gotten was in the discussion archives for Traingle.Net where someone asked a similar question (discussion id 632458) but unfortunately, the answer was not what I was looking for.
My goal here is to make a destructible wall in Unity where, when the player shoots the wall, it will create a hole in the wall (like in Rainbow Six Siege).
Here's what I did for my original implementation:
Create initial triangulation using the four corners of the wall.
When the player shoots, perform a raycast, if the raycast intersects with the wall then add the point of intersection to the polygon variable and re-triangulate the entire mesh using that variable.
Draw new triangulation on the wall as a texture to visualise what's happening.
Repeat.
As you can see, step 2 is the problem.
Because I re-triangulate the entire mesh every time the player hits the wall, the more times the player hits the wall the slower the triangulation gets as the number of vertices rises. This could be fine I guess, but I want destructible walls to play a major role in my game so this is not acceptable.
So, digging through the Triangle.Net source code, I find an internal method called InsertVertex. The summary for this method states:
Insert a vertex into a Delaunay triangulation, performing flips as necessary to maintain the Delaunay property.
This would mean I wouldn't have to re-triangulate every time the player shoots!
So I get to implementing this method, and...it doesn't work. I get an error like the one below:
NullReferenceException: Object reference not set to an instance of an object
TriangleNet.TriangleLocator.PreciseLocate (TriangleNet.Geometry.Point searchpoint, TriangleNet.Topology.Otri& searchtri, System.Boolean stopatsubsegment) (at Assets/Triangle.NET/TriangleLocator.cs:146)
I have been stuck on this problem for days and I cannot solve it for the life of me! If anyone who is knowledgeable enough with the Triangle.NET library would be willing to help me I would be so grateful! Along with that, if there is a better alternative to either the implementation or library I'm using (for my purpose which I outlined above) that would also be awesome!
Currently, how I've set up the scene is really simple, I just have a quad which I scaled up and added the script below to it as a component. I then linked that component to a shoot raycast script attached to the Main Camera:
How the scene is setup.
What it looks like in Play Mode.
The exact Triangle.Net repo I cloned is this one.
My code is posted below:
using UnityEngine;
using TriangleNet.Geometry;
using TriangleNet.Topology;
using TriangleNet.Meshing;
public class Delaunay : MonoBehaviour
{
[SerializeField]
private int randomPoints = 150;
[SerializeField]
private int width = 512;
[SerializeField]
private int height = 512;
private TriangleNet.Mesh mesh;
Polygon polygon = new Polygon();
Otri otri = default(Otri);
Osub osub = default(Osub);
ConstraintOptions constraintOptions = new ConstraintOptions() { ConformingDelaunay = true };
QualityOptions qualityOptions = new QualityOptions() { MinimumAngle = 25 };
void Start()
{
osub.seg = null;
Mesh objMesh = GetComponent<MeshFilter>().mesh;
// Add four corners of wall (quad in this case) to polygon.
//foreach (Vector3 vert in objMesh.vertices)
//{
// Vector2 temp = new Vector2();
// temp.x = map(vert.x, -0.5f, 0.5f, 0, 512);
// temp.y = map(vert.y, -0.5f, 0.5f, 0, 512);
// polygon.Add(new Vertex(temp.x, temp.y));
//}
// Generate random points and add to polygon.
for (int i = 0; i < randomPoints; i++)
{
polygon.Add(new Vertex(Random.Range(0.0f, width), Random.Range(0.0f, height)));
}
// Triangulate polygon.
delaunayTriangulation();
}
// When left click is pressed, a raycast is sent out. If that raycast hits the wall, updatePoints() is called and is passed in the location of the hit (hit.point).
public void updatePoints(Vector3 pos)
{
// Convert pos to local coords of wall.
pos = transform.InverseTransformPoint(pos);
Vertex newVert = new Vertex(pos.x, pos.y);
//// Give new vertex a unique id.
//if (mesh != null)
//{
// newVert.id = mesh.NumberOfInputPoints;
//}
// Insert new vertex into existing triangulation.
otri.tri = mesh.dummytri;
mesh.InsertVertex(newVert, ref otri, ref osub, false, false);
// Draw result as a texture onto the wall so to visualise what is happening.
draw();
}
private void delaunayTriangulation()
{
mesh = (TriangleNet.Mesh)polygon.Triangulate(constraintOptions, qualityOptions);
draw();
}
void draw()
{
Texture2D tx = new Texture2D(width, height);
// Draw triangulation.
if (mesh.Edges != null)
{
foreach (Edge edge in mesh.Edges)
{
Vertex v0 = mesh.vertices[edge.P0];
Vertex v1 = mesh.vertices[edge.P1];
DrawLine(new Vector2((float)v0.x, (float)v0.y), new Vector2((float)v1.x, (float)v1.y), tx, Color.black);
}
}
tx.Apply();
this.GetComponent<Renderer>().sharedMaterial.mainTexture = tx;
}
// Bresenham line algorithm
private void DrawLine(Vector2 p0, Vector2 p1, Texture2D tx, Color c, int offset = 0)
{
int x0 = (int)p0.x;
int y0 = (int)p0.y;
int x1 = (int)p1.x;
int y1 = (int)p1.y;
int dx = Mathf.Abs(x1 - x0);
int dy = Mathf.Abs(y1 - y0);
int sx = x0 < x1 ? 1 : -1;
int sy = y0 < y1 ? 1 : -1;
int err = dx - dy;
while (true)
{
tx.SetPixel(x0 + offset, y0 + offset, c);
if (x0 == x1 && y0 == y1) break;
int e2 = 2 * err;
if (e2 > -dy)
{
err -= dy;
x0 += sx;
}
if (e2 < dx)
{
err += dx;
y0 += sy;
}
}
}
private float map(float from, float fromMin, float fromMax, float toMin, float toMax)
{
float fromAbs = from - fromMin;
float fromMaxAbs = fromMax - fromMin;
float normal = fromAbs / fromMaxAbs;
float toMaxAbs = toMax - toMin;
float toAbs = toMaxAbs * normal;
float to = toAbs + toMin;
return to;
}
}
Great news! I've managed to fix the issue. InsertVertex() doesn't actually add the new vertex to the list of vertices! So this means that when it tried to triangulate, it was trying to point to the new vertex but it couldn't (because that vertex wasn't in the list). So, to solve this, I just manually add my new vertex to the list of vertices in the mesh, before calling InsertVertex(). Note: When you do this, you also need to manually set the vertex's id. I set the id to the size of the list of vertices because I was adding all new vertices to the end of the list.
// When left click is pressed, a raycast is sent out. If that raycast hits the wall, updatePoints() is called and is passed in the location of the hit (hit.point).
public void updatePoints(Vector3 pos)
{
// Convert pos to local coords of wall. You don't need to do this, i do it because of my draw() method where i map everything out onto a texture and display it.
pos = transform.InverseTransformPoint(pos);
pos.x = map(pos.x, -0.5f, 0.5f, 0, 512);
pos.y = map(pos.y, -0.5f, 0.5f, 0, 512);
Vertex newVert = new Vertex(pos.x, pos.y);
// Manually add new vertex to list of vertices.
newVert.id = mesh.vertices.Count;
mesh.vertices.Add(newVert.id, newVert);
//Doing just the first line gave me a null pointer exception. Adding the two extra lines below it fixed it for me.
otri.tri = mesh.dummytri;
otri.orient = 0;
otri.Sym();
// Insert new vertex into existing triangulation.
mesh.InsertVertex(newVert, ref otri, ref osub, false, false);
// Draw result as a texture onto the wall so to visualise what is happening.
draw();
}
Hope this will help someone done the road!

How to change Sprite Image when it reaches 90 degrees?

I say that I am a beginner.
I have a question during the project.
I'm currently implementing a card-matching game.
When I start the game, The image is loaded from the external path (D: / ..).
My question is in the code below.
public void createCardList()
{
int count_x = 0;
int count_y = 0;
GameObject parent_area = GameObject.Find("GameMain");
List<int> num = createRandomIndex(createArrayIndex());
for (int i = 0; i < card_list.Count; ++i)
{
if ((i % CARD_ROWS) == 0 && i > 0)
{
count_y += 1;
count_x = 0;
}
GameObject card_prefab_load = Resources.Load("Prefabs/card") as GameObject;
GameObject card_prefab_instantiate = Instantiate(card_prefab_load, card_prefab_load.transform.position, Quaternion.identity);
float card_position_x = (CARD_WIDTH + CARD_SPACE) * (i % CARD_ROWS) - 290f;
//Debug.Log("card_position_x" + card_position_x);
float card_position_y = count_y * (CARD_HEIGHT + CARD_SPACE) - 280f;
//Debug.Log("card_position_y" + card_position_y);
card_prefab_instantiate.transform.SetParent(parent_area.transform);
card_prefab_instantiate.transform.name = "card_" + num[i];
card_prefab_instantiate.transform.localScale = new Vector3(1f, 1f, 1f);
card_prefab_instantiate.transform.localPosition = new Vector3(card_position_x, card_position_y, 1f);
StartCoroutine(firstRotateOriginalImage());
}
}
// Rotate image
private IEnumerator firstRotateOriginalImage()
{
yield return new WaitForSeconds(2f);
GameObject findCardList = GameObject.Find("GameMain");
for (int i = 0; i < findCardList.transform.childCount; ++i)
{
// I don't know what code to put in this part.
}
}
What I want to implement is below.
When the card rotation value reaches 90 degrees,How to change an externally imported image to a Sprite Image of a child GameObject?
How to rotate the child objects 360 degrees after the first task is completed?
For example, the picture below.
Arrows indicate the order in which cards are flipped.
also, Of the 12 GameObjects, Six GameObjects try to implement a common image.
I don't know much. I need your help.
There are many ways to do that...
transform.Rotate(...)
transform.RotateAround(...)
transform.localEulerAngles = transform.localEulerAngles.X|Y|Z +
amount
transform.localRotation = transform.localRotation*relativeRotation
/*= a Quaternion*/
Something else entirely...
I'm a doubtful regarding how well I understand your question...
But it seems like you want to simply flip the cards over don't you?
The approach I'd take is to have each card as the combination of the face (rotated 180 degrees in Y) and the back, both being children of an empty GameObject.
That way you could simply rotate the Card object using transform.Rotate(0, 180, 0)
To use it in a coroutine you could do
//Speed of animation (here 0.55 seconds)
float degreesPerSecond = 200f;
//The amount you want to rotate
float maxDegrees = 180f;
//Animate
for (float f = maxDegrees; f < 0;)
{
//How much to rotate
float rot = degreesPerSecond * Time.deltaTime;
//Rotate children
foreach(var child in transform)
child.Rotate(0, rot, 0);
//Record rotation
f -= rot;
//Wait next frame
yield return null;
}
//Round to desired rotation
foreach(var child in transform)
child.position = new Vector3(child.position.x, maxDegrees, child.position.z);

Categories