I'm using Roslyn from Sep 2012. I'm trying to create instance of a class from file. Problem is that the class is implementing and overriding some methods. When I try to run a run-time compile a get errors like:
error CS0122: 'GameObject' is inaccessible due to its protection level Roslyn.Compilers.CSharp.Diagnostic
error CS0115: 'rotate(float)': no suitable method found to override Roslyn.Compilers.CSharp.Diagnostic
It looks like class doesn't see interface and overriding functions. But my Compilation looks:
var comp = Compilation.Create("Test.dll"
, syntaxTrees: new[] { syntaxTree }
, references: new[] {
MetadataFileReference.CreateAssemblyReference("mscorlib"),
new MetadataFileReference(typeof(Game.IGameObjectInterface).Assembly.Location),
new MetadataFileReference(typeof(Team).Assembly.Location),
new MetadataFileReference(typeof(System.Linq.Enumerable).Assembly.Location),
new MetadataFileReference(typeof(LinkedList<>).Assembly.Location),
}
, options: new CompilationOptions(OutputKind.DynamicallyLinkedLibrary)
);
Reference on the interface is added.
What am I doing wrong?
EDIT GameObject
abstract class GameObject: IGameObject {
protected string name;
protected Entity entity;
.
.
.
//Look here create file load file
static GameObject() {
gameActionsPermitions = new Dictionary<string, List<IStaticGameObject>>();
gameActions = new Dictionary<string, IGameAction>();
IGameAction o = (IGameAction)System.Reflection.Assembly.GetExecutingAssembly().CreateInstance("Strategy.GroupControl.Game_Objects.GameActions.Produce");
gameActions.Add(o.getName(), o);
gameActionsPermitions.Add(o.getName(), new List<IStaticGameObject>());
}
.
.
.
public abstract void rotate(float f);
public abstract void nonActiveRotate(float f);
protected abstract void onDisplayed();
.
.
.
}
And inteface IGameObject
interface IGameObject{
void rotate(float f);
void nonActiveRotate(float f);
void changeVisible(bool visible);
string getName();
string getMesh();
bool tryExecute(string executingAction);
Team Team { get; set; }
}
And function from file is
public override void rotate(float f) {
tryExecute("Produce");
sceneNode.Roll(new Mogre.Degree((float)(mFlySpeed * 0.5 *f)));
//position in LinkedList now moving
if (!mFlying) {
if (nextLocation()) {
mFlying = true;
mDestination = circularPositions.First.Value; //get the next destination.
prepareNextPosition();
//update the direction and the distance
mDirection = mDestination - sceneNode.Position;
mDistance = mDirection.Normalise();
} else {
}//nothing to do so stay in position
} else {
double move = mFlySpeed * f;
mDistance -= move;
if (mDistance <= .0f) { //reach destination
travelledInvisible = 0;
sceneNode.Position = mDestination;
mDirection = Mogre.Vector3.ZERO;
mFlying = false;
} else {
sceneNode.Translate(mDirection * (float)move);
}
}
}
EDIT2:
file with class
using System;
using System.Collections.Generic;
using System.Linq;
using Mogre;
using Strategy.TeamControl;
namespace Strategy.GroupControl.Game_Objects.StaticGameObjectBox {
class Planet : GameObject {
protected double mDistance = 0.0f; //distance to positoin
protected Mogre.Vector3 mDirection = Mogre.Vector3.ZERO; // The direction the object is moving
protected bool mFlying = false; //bool to detect if object walking or stay
protected double mFlySpeed = 200f; //speed of planet
protected double travelledInvisible;
private static Random random = new Random();
///testing
public Planet() {
}
public Planet(string s) {
name = s;
}
//end
public Planet(string name, string mesh, Team myTeam, Mogre.SceneManager manager, double distanceFromCenter,
Vector3 center, int circularNum = 30) {
this.name = name;
this.mesh = mesh;
planetTeam = myTeam;
this.manager = manager;
//prepare list of positions
circularPositions = calculatePositions(circularNum, distanceFromCenter,center);
randomizeStartPosition(circularNum); // randomize start position
mDestination = circularPositions.First();
//Mogre inicialization of object
entity = manager.CreateEntity(name, mesh);
}
/// <summary>
/// Rotating in visible mood, it means when planet is in active solar system
/// </summary>
/// <param name="f">delay between frames</param>
public override void rotate(float f) {
tryExecute("Produce");
sceneNode.Roll(new Mogre.Degree((float)(mFlySpeed * 0.5 *f)));
//position in LinkedList now moving
if (!mFlying) {
if (nextLocation()) {
mFlying = true;
mDestination = circularPositions.First.Value; //get the next destination.
prepareNextPosition();
//update the direction and the distance
mDirection = mDestination - sceneNode.Position;
mDistance = mDirection.Normalise();
} else {
}//nothing to do so stay in position
} else {
double move = mFlySpeed * f;
mDistance -= move;
if (mDistance <= .0f) { //reach destination
travelledInvisible = 0;
sceneNode.Position = mDestination;
mDirection = Mogre.Vector3.ZERO;
mFlying = false;
} else {
sceneNode.Translate(mDirection * (float)move);
}
}
}
/// <summary>
/// Function calculate moves in invisible mode
/// </summary>
/// <param name="f">delay between frames</param>
public override void nonActiveRotate(float f) {
tryExecute("Produce");
if (!mFlying) {
if (nextLocation()) {
mFlying = true;
mDestination = circularPositions.First.Value; //get the next destination.
prepareNextPosition();
mDistance = mDirection.Normalise();
} else {
}//nothing to do so stay in position
} else {
double move = mFlySpeed * f;
mDistance -= move;
if (mDistance <= .0f) { //reach destination
travelledInvisible = 0;
mDirection = Mogre.Vector3.ZERO;
mFlying = false;
} else {
travelledInvisible += move;
}
}
}
//own functions
/// <summary>
/// Randomize starting position of planet
/// </summary>
/// <param name="max">max of rotates</param>
private void randomizeStartPosition(int max) {
for (int i = 0; i < getRandomNumber(max); i++) {
prepareNextPosition();
}
}
private static int getRandomNumber(int max) {
return random.Next(max);
}
/// <summary>
/// Cyclic remove from LinkedList and add on the end
/// </summary>
private void prepareNextPosition() {
var tmp = circularPositions.First; //save the node that held it
circularPositions.RemoveFirst(); //remove that node from the front of the list
circularPositions.AddLast(tmp); //add it to the back of the list.
}
/// <summary>
/// Calculate posistion on circle represent as ngon
/// </summary>
/// <param name="circularNum">Number of positions on circle</param>
/// <param name="distanceFromCenter">radius on circle</param>
/// <returns>linkedList with position on ngon (circle)</returns>
private LinkedList<Mogre.Vector3> calculatePositions(int circularNum, double distanceFromCenter,Vector3 center) {
var list = new LinkedList<Mogre.Vector3>();
for (int i = 0; i < circularNum; i++) {
double x = System.Math.Cos(i * 2 * System.Math.PI / circularNum) * distanceFromCenter;
double y = System.Math.Sin(i * 2 * System.Math.PI / circularNum) * distanceFromCenter;
list.AddFirst(new Mogre.Vector3((float)x + center.x, 0, (float)y)+ center.y);
}
return list;
}
/// <summary>
/// The NextLocation() check if exist next location to move
/// </summary>
/// <returns>true ->exist / false -> not exist</returns>
private bool nextLocation() {
if (circularPositions.Count == 0) {
return false;
}
return true;
}
/// <summary>
/// Called when object is displayed (invisible to visible)
/// </summary>
protected override void onDisplayed() {
sceneNode.Position = mDestination;
mFlying = false; //jump correction
}
}
}
These look like standard compiler errors.
I suspect your GameObject class is not declared as public. This will cause it to not be visible to the assembly you're creating via Roslyn, as it's compiling a new (separate) assembly from the one in which your types are defined.
If you make your types public, this error will likely go away.
Related
The gameobjects in the array (SequenceItems) have at least 1 child, and in some cases 1 child and 1 grandchild.
the Mesh Swapping works but it is very jittery when there are two players in the room. Also, when I place a sphere inside the mesh that collides with another mesh, the for loop (resizeCube) seems to stop But the OnNext() continues.
Edit** I changed my code to swap meshes instead of adjusting the scale but I am still having the same issues.
Here is my code:
using System.Collections;
using System.Linq;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Photon.Pun;
using Photon.Realtime;
using Microsoft.MixedReality.Toolkit.UI;
using TMPro;
public class PCSequencer : MonoBehaviour
{
public bool play = true;
[Header("Sequence Controller")]
private PhotonView myPV;
public Mesh on;
public Mesh off;
[Tooltip("Drag in a bunch of GameObject you want in the sequence (must be in correct order before dragging in).")]
/// <summary>
/// List of GameObjects in sequence (must be in correct order)
/// </summary>
public GameObject[] SequenceItems;
[Tooltip("The amount of time in seconds between sequence items.")]
/// <summary>
/// The interval of time in seconds between sequences.
/// </summary>
public float sequenceIntervalDelay = 2f;
private int _currentIndex;
[SerializeField]
private TextMeshPro textMesh = null;
/// <summary>
/// The current sequence index.
/// </summary>
public int CurrentIndex
{
get { return _currentIndex; }
set
{
if (value != _currentIndex)
{
// Ensure current index isn't more/less than the index bounds of the given Sequence Items...
if (_currentIndex >= 0 || _currentIndex <= SequenceItems.Length - 1)
{
// Debug.Log("is this a thing?: " + value);
_currentIndex = value;
textMesh.text = _currentIndex.ToString();
}
}
}
}
/// <summary>
/// Get things ready before first update occurs.
/// </summary>
void Start()
{
myPV = GetComponent<PhotonView>();
// Ensure Sequence is reset and only the first Sequence Item is visible...
ResetSequence();
OnPlay();
}
public void Update()
{
if (Input.GetKeyDown("space"))
{
OnPlay();
print("space key was pressed");
}
}
/// <summary>
/// On play button pressed.
/// </summary>
private void OnPlay()
{
// Reset sequence back to start...
if (CurrentIndex == SequenceItems.Length - 1)
{
ResetSequence();
}
// When Play button press, repeat call the OnNext() method...
StartCoroutine("func");
// InvokeRepeating("OnNext", sequenceIntervalDelay, sequenceIntervalDelay);
Debug.Log("Sequence Item " + CurrentIndex);
}
IEnumerator func()
{
while (true)
{
OnNext();
yield return new WaitForSecondsRealtime(sequenceIntervalDelay); //Wait 1 second
}
}
private void OnNext()
{
if (play == true)
{
if (CurrentIndex < SequenceItems.Length)
{
// Debug.Log("what the index: " + CurrentIndex);
if (PhotonNetwork.IsMasterClient)
{
myPV.RPC("ResizeCube", RpcTarget.All, CurrentIndex);
}
//ResizeCube(CurrentIndex);
if (PhotonView.Find(SequenceItems[CurrentIndex].GetComponent<PhotonView>().ViewID).gameObject.GetComponent<pcInteraction>().isActiveToPlay == true)
{
Debug.Log("PlayNOte: " + CurrentIndex);
SerialCommunication.sendNote(PhotonView.Find(SequenceItems[CurrentIndex].GetComponent<PhotonView>().ViewID).GetComponent<pcInteraction>().allCheckInsideSphere.currentNote);
Debug.Log("sending note to arduino from sequencer");
}
else if (SequenceItems[CurrentIndex].GetComponent<pcInteraction>().isActiveToPlay == false)
{
}
CurrentIndex++;
}
else
{
ResetSequence();
}
}
}
public void OnSliderUpdated(SliderEventData eventData)
{
float current = float.Parse($"{eventData.NewValue:F2}");
myPV.RPC("SpeedAdjust", RpcTarget.All, current);
}
[PunRPC]
void SpeedAdjust(float speed)
{
sequenceIntervalDelay = speed;
}
[PunRPC]
void ResizeCube(int index)
{
{
for (int i = 0; i < SequenceItems.Length; i++)
{
if (i == index)
SequenceItems[i].GetComponent<MeshFilter>().mesh = on;
// PhotonView.Find(SequenceItems[i].GetComponent<PhotonView>().ViewID).gameObject.GetComponent<MeshFilter>().mesh = on;
// SequenceItems[i].gameObject.GetComponent<MeshFilter>().mesh = on;
else
SequenceItems[i].GetComponent<MeshFilter>().mesh = off;
//PhotonView.Find(SequenceItems[i].GetComponent<PhotonView>().ViewID).gameObject.GetComponent<MeshFilter>().mesh = off;
// SequenceItems[i].gameObject.GetComponent<MeshFilter>().mesh = off;
//PhotonView.Find(SequenceItems[i].GetComponent<PhotonView>().ViewID).gameObject.transform.localScale = new Vector3(1f, 1f, 1f);
}
}
}
/// <summary>
/// Resests the sequence back to the beginning.
/// </summary>
private void ResetSequence()
{
foreach (var go in SequenceItems)
{
// go.SetActive(false);
// go.GetComponent<MeshRenderer>().material.color = Color.white;
}
// SequenceItems.First().SetActive(true);
CurrentIndex = 0;
}
}
Please, help me.
The farther from the center of the screen the higher / lower the car speed. Car's RigidBody2D.mass = 1000, wheels's mass = 50. The car object has 2 'WheelJoint2D' components (connected RigidBody = frontwheel and backwheel) and useMotor = true, maximumMotorForce = 10000 (by default).
Here is part of my code (C#):
[RequireComponent(typeof(Rigidbody2D), typeof(WheelJoint2D))]
public class CarBaseMovement : MonoBehaviour, IVehicleMovable
{
public const float GRAVITY = 9.81f;
[Header("Wheels Joint")]
[SerializeField] protected WheelJoint2D _frontWheelJoint;
[SerializeField] protected WheelJoint2D _backWheelJoint;
private int _centerScreenX;
protected Rigidbody2D _rigidBody2D;
private float _movementInput;
private float _deltaMovement;
private float _physicValue;
private JointMotor2D _wheelMotor;
private void Start()
{
// set center screen width
_centerScreenX = Screen.width / 2;
_rigidBody2D = GetComponent<Rigidbody2D>();
if (_rigidBody2D == null || _frontWheelJoint == null || _backWheelJoint == null)
{
throw new ArgumentNullException();
}
_wheelMotor = _backWheelJoint.motor;
}
protected virtual void Update()
{
// _movementInput = Input.GetAxis("Horizontal");
if (Input.GetMouseButton(0))
{
_deltaMovement = Input.mousePosition.x;
GetTouch(_deltaMovement);
SetVelocity();
SetWheelsMotorSpeed();
}
}
/// <summary>
/// Get touch/mouseclick position to determine speed
/// </summary>
/// <param name="touchPos">touch/mouseclick position</param>
protected void GetTouch(float touchPos)
{
if (touchPos > _centerScreenX)
{
_movementInput = touchPos - _centerScreenX;
}
if (touchPos < _centerScreenX)
{
_movementInput = _centerScreenX - touchPos;
}
}
/// <summary>
/// Set velocity
/// </summary>
private void SetVelocity()
{
_physicValue = GRAVITY * Mathf.Sin((transform.eulerAngles.z * Mathf.PI) / 180f) * 80f;
_wheelMotor.motorSpeed = Mathf.Clamp(
_wheelMotor.motorSpeed - ( _movementInput - _physicValue) * Time.deltaTime,
-7000f,
7000f);
}
/// <summary>
/// Set wheels motor speed
/// </summary>
private void SetWheelsMotorSpeed()
{
_frontWheelJoint.motor = _backWheelJoint.motor = _wheelMotor;
}
}
I'm working in a Unity game with Mapbox SDK. I have this script to spawn in the map only one prefab in multiple positions. How can I do to spawn several different prefabs each one in one different position?
public class SpawnOnMap : MonoBehaviour
{
[SerializeField]
AbstractMap _map;
[SerializeField]
[Geocode]
string[] _locationStrings;
Vector2d[] _locations;
[SerializeField]
float _spawnScale = 100f;
[SerializeField]
GameObject _markerPrefab;
List<GameObject> _spawnedObjects;
void Start()
{
_locations = new Vector2d[_locationStrings.Length];
_spawnedObjects = new List<GameObject>();
for (int i = 0; i < _locationStrings.Length; i++)
{
var locationString = _locationStrings[i];
_locations[i] = Conversions.StringToLatLon(locationString);
var instance = Instantiate(_markerPrefab);
instance.transform.localPosition = _map.GeoToWorldPosition(_locations[i], true);
instance.transform.localScale = new Vector3(_spawnScale, _spawnScale, _spawnScale);
_spawnedObjects.Add(instance);
}
}
private void Update()
{
int count = _spawnedObjects.Count;
for (int i = 0; i < count; i++)
{
var spawnedObject = _spawnedObjects[i];
var location = _locations[i];
spawnedObject.transform.localPosition = _map.GeoToWorldPosition(location, true);
spawnedObject.transform.localScale = new Vector3(_spawnScale, _spawnScale, _spawnScale);
}
}
}
I use struct for coordinates:
public struct Point
{
/// <summary>
/// The x position
/// </summary>
public int X { get; set; }
/// <summary>
/// The y position
/// </summary>
public int Y { get; set; }
/// <summary>
/// Sets the values of the struct
/// </summary>
/// <param name="x">initial x</param>
/// <param name="y">initial y</param>
public Point(int x, int y)
{
this.X = x;
this.Y = y;
}
}
Then I used this struct from another class,
blueSpawn and redSpawn are different points and
you can use different prefab for them like that:
another class:
private Point blueSpawn, redSpawn;
//this the method for your question
private void SpawnPortals()
{
//Spawns the blue portal
blueSpawn = new Point(0, 0);
Instantiate(bluePortalPrefab, Tiles[BlueSpawn].GetComponent<TileScript>().WorldPosition, Quaternion.identity);
//GameObject tmp = (GameObject)Instantiate(bluePortalPrefab, Tiles[BlueSpawn].GetComponent<TileScript>().WorldPosition, Quaternion.identity);
//You can save like a "tmp" if you need.
//Spawns the red portal
redSpawn = new Point(11, 6);
Instantiate(redPortalPrefab, Tiles[redSpawn].GetComponent<TileScript>().WorldPosition, Quaternion.identity);
}
TileScript and Portal are another classes but you can ignore them. By the way You can call this method in Start()
I'm currently working on a set of scripts. The collective purpose of these scripts is to create a controller object that, upon the user clicking on an object, will check if the object is a GridCell object then add it to a list of positions; the list of positions will be followed by the controller as a path.
A secondary effect of the script is that it should draw a line representing the path created by the list of positions. There are five different scripts in the entire project, here they are:
GridController.cs (Primary script)
using UnityEngine;
using System.Collections;
public class GridController : MonoBehaviour {
private RaycastHit rayhit;
public Path controllerPath;
public GLLineController lineController;
public bool playerTransforming = false;
public Vector2 currentTarget = Path.VECTORNULL;
// Use this for initialization
void Start () {
controllerPath = new Path();
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButtonDown(0))
{
if (RaycastHitGridcell(Camera.main.ScreenPointToRay(Input.mousePosition), out this.rayhit))
{
Vector2 tempRayhitV = new Vector2(rayhit.transform.position.x, rayhit.transform.position.y);
controllerPath.Add(tempRayhitV);
if (controllerPath.PathList2D.Count < 1)
{
lineController.lineList.Add(new Line(transform.position,
new Vector3(tempRayhitV.x, tempRayhitV.y),
Screen.width,
Screen.height,
Camera.main,
false));
}
else
{
Vector2 lastInLineList = controllerPath.PathList2D[controllerPath.PathList2D.Count - 1];
lineController.lineList.Add(new Line(new Vector3(lastInLineList.x, lastInLineList.y),
new Vector3(tempRayhitV.x, tempRayhitV.y),
Screen.width,
Screen.height,
Camera.main,
false));
}
}
}
#region tryNext
/*Vector2 nv2;
if (!playerTransforming && controllerPath.TryNext(new Vector2(transform.position.x, transform.position.y), out nv2, out this.playerTransforming))
{
this.transform.Translate(nv2.x, nv2.y, 0f);
}*/
if (!playerTransforming && controllerPath.PathList2D.Count > 1)
{
Vector2 nv2 = controllerPath.Next();
if (nv2 != Path.VECTORNULL)
{
playerTransforming = true;
currentTarget = nv2;
this.transform.Translate(new Vector3(nv2.x, nv2.y, 0f));
}
}
if (currentTarget != Path.VECTORNULL && (Mathf2.Approximately(currentTarget.x, transform.position.x, 0.001f) &&
Mathf2.Approximately(currentTarget.y, transform.position.y, 0.001f)))
{
playerTransforming = false;
currentTarget = Path.VECTORNULL;
}
#endregion
}
public static bool RaycastHitGridcell(Ray ray, out RaycastHit hit)
{
RaycastHit tHit;
if (Physics.Raycast(ray, out tHit))
{
if (tHit.transform.gameObject.tag == "GridCell")
{
hit = tHit;
return true;
}
}
hit = tHit;
return false;
}
}
Path.cs (Represents a list of positions to follow)
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Path {
/// <summary>
/// List that represents a path of positions.
/// </summary>
public List<Vector2> PathList2D = new List<Vector2>();
/// <summary>
/// Instantiate a constant variable that stores the default NULL value for a vector2 x value.
/// </summary>
public const float VECTORNULL_X = float.NaN;
/// <summary>
/// Instantiate a constant variable that stores the default NULL value for a vector2 y value.
/// </summary>
public const float VECTORNULL_Y = float.NaN;
public static Vector2 VECTORNULL_V2
{
get { return new Vector2(VECTORNULL_X, VECTORNULL_Y); }
}
/// <summary>
/// Add an object to the end of the vector2 list.
/// </summary>
/// <param name="position">Object to add.</param>
public void Add(Vector2 position)
{
PathList2D.Add(position);
}
/// <summary>
/// Remove a specific object from the vector2 list.
/// </summary>
/// <param name="position">Object to remove.</param>
public void Remove(Vector2 position)
{
PathList2D.Remove(position);
}
/// <summary>
/// Remove an object at a specified index within the vector2 list.
/// </summary>
/// <param name="index">Indext to remove the object at.</param>
public void Remove(int index)
{
PathList2D.RemoveAt(index);
}
/// <summary>
/// Remove the current position.
/// </summary>
/// <returns>VECTORNULL if path isn't long enough. The next position if the path is long enough.</returns>
public Vector2 Next()
{
if (PathList2D.Count < 1)
return VECTORNULL_V2;
Vector2 nvt = PathList2D[0];
PathList2D.RemoveAt(0);
return nvt;
}
}
public class SpecialVector2
{
private float _X, _Y;
public float X
{
get { return (Null ? float.NaN : _X); }
set { _X = value; }
}
public float Y
{
get { return (Null ? float.NaN : _Y); }
set { _Y = value; }
}
public bool Null = false;
public SpecialVector2(float x, float y)
{
this._X = x;
this._Y = y;
}
public SpecialVector2(bool nullFlag)
{
this.Null = nullFlag;
}
public static SpecialVector2 TrueNull()
{
return new SpecialVector2(true);
}
}
Line.cs (Object that represents the vectors for a GL line)
using UnityEngine;
using System.Collections;
public class Line {
public Vector3 StartingVertex;
public Vector3 EndingVertex;
public Line(Vector3 starting, Vector3 ending, int xMax, int yMax, Camera viewport, bool vpCompatible = true)
{
if (!vpCompatible)
{
StartingVertex = new Vector3((starting.x - viewport.transform.position.x) / (float)xMax,
(starting.y - viewport.transform.position.y) / (float)yMax,
0);
EndingVertex = new Vector3((ending.x - viewport.transform.position.x) / (float)xMax,
(ending.y - viewport.transform.position.y) / (float)yMax,
0);
}
else
{
StartingVertex = starting;
EndingVertex = ending;
}
}
}
GLLineController.cs (Script that controls the post rendering of GL lines.)
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class GLLineController : MonoBehaviour {
/// <summary>
/// Material to pass over the line.
/// </summary>
private Material mat;
/// <summary>
/// List of line objects that will represent the vectors for the GL lines.
/// </summary>
public List<Line> lineList = new List<Line>();
// Use this for initialization
void Start () {
CreateLineMaterial();
}
/// <summary>
/// Assign a basic material pass to the mat field.
/// </summary>
public void CreateLineMaterial()
{
if (!mat)
{
mat = new Material("Shader \"Lines/Colored Blended\" {" +
"SubShader { Pass { " +
" Blend SrcAlpha OneMinusSrcAlpha " +
" ZWrite Off Cull Off Fog { Mode Off } " +
" BindChannels {" +
" Bind \"vertex\", vertex Bind \"color\", color }" +
"} } }");
mat.hideFlags = HideFlags.HideAndDontSave;
mat.shader.hideFlags = HideFlags.HideAndDontSave;
}
}
// Update is called once per frame
void Update () {
}
void OnPostRender()
{
GL.PushMatrix();
mat.SetPass(0);
GL.LoadOrtho();
GL.Begin(GL.LINES);
GL.Color(Color.white);
foreach (Line l in lineList)
{
GL.Vertex(l.StartingVertex);
GL.Vertex(l.EndingVertex);
}
GL.End();
GL.PopMatrix();
}
}
Theoretically, these scripts should work semi-perfectly in union, but they don't work at all from what i can tell.
Does anybody have a better way to go about this? Otherwise, does anybody know where my error(s) is/are?
Thank you!
-Tristen H.
I've got a ship that's spawning sprites. There are two types: railgun rounds and missiles. The missiles fire off properly, but the railgun rounds always spawn about one hundred pixels in front of the ship (or at least, it seems to). I'm not sure why this is happening. Also, there are two turrets, when it fires out of one, it's supposed to set a boolean value to true to make it fire out of the other one; when it fires out of that one, it sets the boolean back to false and so on. It always fires out of the first one. Again, no idea why. I've been banging my head against this all day. Here's my code:
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 ShipBattle.Classes.Ships;
using ShipBattle.Classes.Ships.Fighters;
using ShipBattle.Classes.Ships.Projectiles;
using ShipBattle.Classes.Ships.Projectiles.Tauri;
namespace ShipBattle.Classes.Ships.Fighters
{
public class F302 : Ship
{
const double missileMinimumFiringArc = Utilities.NINETY_DEGREES / 2;
const double missileMaximumFiringArc = Utilities.NINETY_DEGREES + (Utilities.NINETY_DEGREES / 2);
const double railgunMinimumFiringArc = 1.5;
const double railgunMaximumFiringArc = 1.6;
const double MISSILES_ROF = 30.0;
protected List<double> CooldownLeft = new List<double>();
private ContentManager content;
public event ShipFired WeaponFired;
public List<NaquadahEnhancedMissile> missiles;
public List<RailgunRound> railgunRounds;
public int[] MissileAmmo { get; set; }
public int[] RailgunAmmo { get; set; }
//Determines which missile/railgun to fire
bool leftMissile = true;
bool leftRailgun = true;
public F302(Vector2 position, ContentManager Content)
{
content = Content;
Texture = content.Load<Texture2D>(#"Textures\Ships\Tauri\Fighters\F302");
Position = position;
Rotation = 0;
#region Physics Stuff
mass = 19200;
force = 76.3f;
acceleration = (force * 1000) / mass;
maxSpeed = Utilities.GetVelocity(acceleration);
#endregion
#region Hull & Shielding
HullIntegrity = 10;
ShieldStrength = 0;
#endregion
#region Weapons!!!
/*
* [0] = Port Missile
* [1] = Starboard Missile
* [2] = Port Railgun
* [3] = Starboard Railgun
*/
//Setup
missiles = new List<NaquadahEnhancedMissile>();
railgunRounds = new List<RailgunRound>();
MissileAmmo = new int[2];
RailgunAmmo = new int[2];
//Port Missile
WeaponRatesOfFire.Add(MISSILES_ROF);
CooldownLeft.Add(0);
WeaponsEnplacements.Add(new Vector2(14, 5));
WeaponEmplacementOffsets.Add(new Vector2(14, 5));
MissileAmmo[0] = 2;
//Starboard Missile
WeaponRatesOfFire.Add(MISSILES_ROF);
CooldownLeft.Add(0);
WeaponsEnplacements.Add(new Vector2(35, 5));
WeaponEmplacementOffsets.Add(new Vector2(35, 5));
MissileAmmo[1] = 2;
//Port Railgun
WeaponRatesOfFire.Add(7.2);
CooldownLeft.Add(0);
WeaponsEnplacements.Add(new Vector2(24, 0));
WeaponEmplacementOffsets.Add(new Vector2(24, 0));
RailgunAmmo[0] = 10000;
//Starboard Railgun
WeaponRatesOfFire.Add(7.2);
CooldownLeft.Add(0);
WeaponsEnplacements.Add(new Vector2(26, 0));
WeaponEmplacementOffsets.Add(new Vector2(26, 0));
RailgunAmmo[1] = 10000;
#endregion
}
protected override void UpdateProjectiles(Vector2 pos)
{
for (int i = 0; i < missiles.Count; i++)
if (missiles[i].Remove)
missiles.RemoveAt(i);
for (int i = 0; i < railgunRounds.Count; i++)
if (railgunRounds[i].Remove)
railgunRounds.RemoveAt(i);
foreach (NaquadahEnhancedMissile nem in missiles)
nem.Update(enemyPos);
foreach (RailgunRound rr in railgunRounds)
rr.Update(enemyPos);
}
protected override void DrawProjectiles(SpriteBatch spriteBatch)
{
foreach (NaquadahEnhancedMissile nem in missiles)
nem.Draw(spriteBatch);
foreach (RailgunRound rr in railgunRounds)
rr.Draw(spriteBatch);
}
protected override void CheckTarget(Ship target)
{
enemyPos = target.Position;
double distance = Vector2.Distance(Position, target.Position);
Vector2 vector1 = Vector2.Normalize(Position - target.Position);
Vector2 vector2 = new Vector2((float)Math.Cos(Rotation), (float)Math.Sin(Rotation));
double angle = Math.Acos(Vector2.Dot(vector1, vector2));
if (angle > missileMinimumFiringArc && angle < missileMaximumFiringArc)
if (distance < 500)
if (((target.HullIntegrity + target.ShieldStrength) - 10) <= 0)
FireMissiles();
if (angle > railgunMinimumFiringArc && angle < railgunMaximumFiringArc)
FireRailguns();
}
protected void FireMissiles()
{
if (leftMissile)
{
if (CooldownLeft[0] <= 0)
{
if (MissileAmmo[0] > 0)
{
NaquadahEnhancedMissile nem = new NaquadahEnhancedMissile(WeaponsEnplacements[0], Rotation, content);
nem.hit += new ProjectileHit(nem_hit);
missiles.Add(nem);
CooldownLeft[0] = WeaponRatesOfFire[0];
CooldownLeft[1] = WeaponRatesOfFire[1];
MissileAmmo[0]--;
leftMissile = false;
}
}
}
else
if (CooldownLeft[1] <= 0)
{
if (MissileAmmo[1] > 0)
{
NaquadahEnhancedMissile nem = new NaquadahEnhancedMissile(WeaponsEnplacements[1], Rotation, content);
nem.hit += new ProjectileHit(nem_hit);
missiles.Add(nem);
CooldownLeft[0] = WeaponRatesOfFire[0];
CooldownLeft[1] = WeaponRatesOfFire[1];
MissileAmmo[1]--;
leftMissile = true;
}
}
}
private void FireRailguns()
{
if (leftRailgun)
{
if (CooldownLeft[2] <= 0)
{
if (RailgunAmmo[0] > 0)
{
RailgunRound rgr = new RailgunRound(WeaponsEnplacements[2], Rotation, content);
rgr.hit += new ProjectileHit(nem_hit);
railgunRounds.Add(rgr);
CooldownLeft[2] = WeaponRatesOfFire[2];
CooldownLeft[3] = WeaponRatesOfFire[3];
RailgunAmmo[0]--;
leftRailgun = false;
}
}
}
else
if (CooldownLeft[3] <= 0)
{
if (RailgunAmmo[1] > 0)
{
RailgunRound rgr = new RailgunRound(WeaponsEnplacements[3], Rotation, content);
rgr.hit += new ProjectileHit(nem_hit);
railgunRounds.Add(rgr);
CooldownLeft[2] = WeaponRatesOfFire[2];
CooldownLeft[3] = WeaponRatesOfFire[3];
MissileAmmo[1]--;
leftRailgun = true;
}
}
}
protected override void Cooldown()
{
for (int f = 0; f < CooldownLeft.Count; f++)
CooldownLeft[f]--;
}
private void nem_hit(Projectile p, EventArgs e)
{
if (p is NaquadahEnhancedMissile)
{
p.Remove = true;
if (targetShip.ShieldStrength > 0)
targetShip.ShieldStrength -= p.Damage;
else
targetShip.HullIntegrity -= p.Damage;
}
else if (p is RailgunRound)
{
p.Remove = true;
if (targetShip.ShieldStrength > 0)
targetShip.ShieldStrength -= p.Damage / 4;
else
targetShip.HullIntegrity -= p.Damage;
}
}
protected override void CleanupProjectiles()
{
missiles.Clear();
railgunRounds.Clear();
}
}
}
And here's the code for the ship class this all inherits from:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using ShipBattle.Classes.Ships.Projectiles;
using ShipBattle.Classes.Ships.Projectiles.Tauri;
namespace ShipBattle.Classes.Ships
{
public abstract class Ship
{
public Texture2D Texture { get; set; }
public Vector2 Position
{
get
{
return _position;
}
set
{
_position = value;
}
}
public float Rotation { get; set; }
private Vector2 _position;
protected Ship targetShip;
protected Vector2 enemyPos;
#region Health & Shielding
public float HullIntegrity { get; set; }
public float ShieldStrength { get; set; }
public bool Remove { get; set; }
#endregion
#region Guns
protected List<Vector2> WeaponsEnplacements = new List<Vector2>();
protected List<Vector2> WeaponEmplacementOffsets = new List<Vector2>();
protected List<double> WeaponRatesOfFire = new List<double>();
/// <summary>
/// The rates of fire for all weapons, represented in terms of the delay between frames
/// </summary>
#endregion
#region Targeting Logic
bool hasTarget = false;
protected int targetHashCode;
Vector2 targetShipPosition;
Ship target;
bool evasive = false;
bool hasRandomTrajectory = false;
bool reachedBounds = false;
bool followingRandom = false;
int timeToFaffAbout = 360;
double randomRotation;
#endregion
#region Physics Stuff
float angleA, b, a, speed = 0;
double turningRadius = 10 * (Math.PI / 180);
//Acceleration
protected int mass; // kg
protected float force; // kN, thruster power
protected float acceleration; // m/s^2
//Velocity
protected float maxSpeed; // m/s, calculated using 30-second burn
protected float initialSpeed = 0;
protected float finalSpeed = 0;
protected float time = 0.016666f;
#endregion
public void Update(List<Ship> ships)
{
if (timeToFaffAbout >= 0)
{
timeToFaffAbout = 360;
followingRandom = false;
}
if (!hasTarget)
{
targetShip = GetTarget(ships);
hasTarget = true;
}
else
{
if (targetShip != null)
{
if (Vector2.Distance(Position, targetShip.Position) < 75)
evasive = true;
else
evasive = false;
if (evasive)
{
if (!hasRandomTrajectory)
{
Random random = new Random();
randomRotation = random.Next((int)(Math.PI * 100));
double negative = random.Next(2);
if (negative == 1)
randomRotation *= -1;
Rotation = (float)randomRotation;
hasRandomTrajectory = true;
}
}
else
{
if (!followingRandom)
{
//Rotate the sprite using the turning radius
Rotation = Utilities.TurnToFace(Position, new Vector2(targetShip.Position.X, targetShip.Position.Y), (float)Rotation, (float)turningRadius);
}
}
KeepOnTheScreen();
//Move the sprite, using KINEMATIC PHYSICS, ***!!! -->goes in the direction set by the rotation algorithm
Move();
CheckTarget(targetShip);
UpdateProjectiles(targetShip.Position);
//Stop targeting a dead enemy
if (targetShip.HullIntegrity <= 0)
hasTarget = false;
}
}
//Recalculate the List<Vector2> weapons enplacements based on the current rotation angle
RecalculateWeaponsPositions();
//Cooldown the guns
Cooldown();
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(Texture, Position, null, Color.White, Rotation, new Vector2(Texture.Width / 2, Texture.Height / 2), 0.5f,
SpriteEffects.None, 0.0f);
if (hasTarget)
DrawProjectiles(spriteBatch);
}
/// <summary>
/// Uses trig and the thruster power to move the ship. b is the y distance to move, a is the x distance to move
/// </summary>
private void Move()
{
if (finalSpeed < maxSpeed)
finalSpeed = speed + (acceleration * time);
angleA = Rotation;
b = (float)Math.Cos(angleA) * finalSpeed;
a = (float)Math.Sin(angleA) * finalSpeed;
_position.Y -= b;
_position.X += a;
speed = finalSpeed;
}
/// <summary>
/// Acquires the closes enemy ship
/// </summary>
/// <param name="ships">The ships to search through</param>
/// <returns></returns>
private Ship GetTarget(List<Ship> ships)
{
CleanupProjectiles();
Ship rVal = null;
int distance = int.MaxValue;
float c;
foreach (Ship ship in ships)
{
c = Vector2.Distance(Position, ship.Position);
if (c < distance)
rVal = ship;
}
return rVal;
}
/// <summary>
/// Reorients the positions of all the weapon positions on this ship
/// </summary>
private void RecalculateWeaponsPositions()
{
for (int i = 0; i < WeaponsEnplacements.Count; i++)
{
WeaponsEnplacements[i] = RotateWeapons(WeaponEmplacementOffsets[i]);
}
}
/// <summary>
/// Recalculates the positions of the weapons on this ship based off their default offset and the current angle
/// </summary>
/// <param name="weapon">The weapon position to recalculate</param>
/// <param name="offset">The default offset of that weapon</param>
private Vector2 RotateWeapons(Vector2 offset)
{
Quaternion rotation = Quaternion.CreateFromAxisAngle(Vector3.Backward, (float)Rotation);
return Vector2.Transform(offset, rotation) + Position;
}
/// <summary>
/// Keeps the ship on the screen
/// </summary>
private void KeepOnTheScreen()
{
if (Position.X > 1019 || Position.X < 5 || Position.Y > 761 || Position.Y < 5)
reachedBounds = true;
else
reachedBounds = false;
if (reachedBounds)
{
followingRandom = true;
if (!followingRandom)
Rotation = Utilities.TurnToFace(Position, new Vector2(1024 / 2, 768 / 2), Rotation, (float)turningRadius);
else
timeToFaffAbout--;
}
}
/// <summary>
/// Checks to see if the target ship is within weapons range
/// </summary>
/// <param name="target"></param>
protected abstract void CheckTarget(Ship target);
/// <summary>
/// Decrements the cooldown of all weapons
/// </summary>
protected abstract void Cooldown();
protected abstract void UpdateProjectiles(Vector2 pos);
protected abstract void DrawProjectiles(SpriteBatch spriteBatch);
protected abstract void CleanupProjectiles();
}
}
If anyone can help me with this, I'd be really appreciative. Thank you!
Why does FireRailguns() execute MissileAmmo[1]--; ?