I'm trying to make a cooldown visual for my game when actions are used. I want the button that I have that is the action to be filled with a grayish semi-transparent color that "unwinds" clockwise (if that makes sense). Games like World of Warcraft do this where the time it takes for the cooldown is the time the angle of the unwinding takes. You can see an example here. In this picture the cooldown is more than 1/2 way finished.
http://www.vbforums.com/attachment.php?attachmentid=101705&stc=1&d=1372575930
I'm playing around with arc drawing but this doesn't give me what I'm after.
if (globalCD)
{
Pen p = new Pen(Color.FromArgb(125, 255, 0, 0), 10);
//e.Graphics.DrawLine(p, new Point(0, 0), new Point(10, 10));
e.Graphics.DrawArc(p, new Rectangle(0, 0, 64, 64), 270, 270);
}
In general, the Graphics class has a FillX method for each DrawX method. In this case the result is sufficiently different that the names actually change a bit, but you likely want the FillPie method.
if (globalCD)
{
Pen p = new Pen(Color.FromArgb(125, 255, 0, 0), 10);
//e.Graphics.DrawLine(p, new Point(0, 0), new Point(10, 10));
e.Graphics.FillPie(p, new Rectangle(0, 0, 64, 64), 270, 270);
}
Related
I have a class called Cube in which I render a basic cube to the screen. I've got it working as far as rendering a basic cube of any scale at origin 0, 0, 0. However, if I want to move the cube, scale any of its axes, or rotate the cube; I have no idea where to begin since I have to achieve this within a Vertex object.
struct Vertex {
Vector3 Position;
Vector3 Normal;
Vector2 TextureUV;
Color Color;
}
To render a cube of size 1000000 I simply fill the Position properties with that value (with regards to negative and positive values to generate the faces).
new Vertex(new Vector3(-1000000, -1000000, -1000000), new Vector3(-1, -1, -1), Color.White);
Cube has four properties:
Position (Vector3).
Scale (Vector3).
Rotation (Vector3).
Color (SharpDX.Color).
My question is, as I am specifying Vertex locations, how can I calculate the new position when rotation and position are applied?
I attempted basic subtraction and addition which simply scales the cube differently and the origin remains at 0, 0, 0 (please don't mind the shorthand).
new Vertex(new Vector3(P.X - S.X, P.Y - S.Y, P.Z - S.Z), new Vector3(1, 1, 1), Color.White);
The above isn't the exact code as it is on a different computer currently.
If you need additional details, please let me know and I will clarify.
The Question
How can I set the position of the vertices based on the supplied position, scale, and rotation vectors?
Test Case
The following test cases are for position only and are to show you how I will test the answers given.
// Renders at origin.
Cube myCube = new Cube(new Vector3(0, 0, 0), new Vector3(100, 100, 100), Color.White);
// Renders to the left.
Cube myCubeLeft = new Cube(new Vector3(-250, 0, 0), new Vector3(100, 100, 100), Color.White);
// Renders to the right.
Cube myCubeRight = new Cube(new Vector3(250, 0, 0), new Vector3(100, 100, 100), Color.White);
// Renders above.
Cube myCubeUp = new Cube(new Vector3(0, -250, 0), new Vector3(100, 100, 100), Color.White);
// Renders below.
Cube myCubeDown = new Cube(new Vector3(0, 250, 0), new Vector3(100, 100, 100), Color.White);
I will add rotation and scaling test cases later if needed.
I have written a script for a procedural cube. Basically I want to make a building whose width, length and height I can control through parameters. So by changing parameters I can make different shapes like windows and door and roof and many more. But I don't have any idea how to do that. How to reuse this script for different shapes?
using UnityEngine;
public class genralWindows: MonoBehaviour
{
public float height = 0.8 f;
public float width = 0.6 f;
public float length = 0;
void Start()
{
cube();
gameObject.GetComponent < Renderer > ().material.color = Color.white;
}
public void cube()
{
MeshFilter mf1 = GetComponent < MeshFilter > ();
Mesh mesh1 = mf1.mesh;
//vertices
Vector3[] vertices = new Vector3[]
{
//front face
new Vector3(-width, height, length), //left top front, 0
new Vector3(width, height, length), //right top front, height
new Vector3(-width, -height, length), //left bottom front, 2
new Vector3(width, -height, length), //right bottom front, width
//BACK FACE
new Vector3(width, height, -length), //right top back, 4
new Vector3(-width, height, -length), //left top back, length
new Vector3(width, -height, -length), //right bottom back, 6
new Vector3(-width, -height, -length), //left bottom back, 7
//LEFT FACE
new Vector3(-width, height, -length), //left top back,width
new Vector3(-width, height, length), //left top front,9
new Vector3(-width, -height, -length), //left bottom back,height0,
new Vector3(-width, -height, length), //left bottom front,heightheight
//RIGHT FACE
new Vector3(width, height, length), //right top front height2
new Vector3(width, height, -length), //right top back heightwidth
new Vector3(width, -height, length), //right bottom front height4
new Vector3(width, -height, -length), //right bottom back heightheight
//TOP FACE
new Vector3(-width, height, -length), //left top back height6
new Vector3(width, height, -length), //right top back height7
new Vector3(-width, height, length), //left top front heightwidth
new Vector3(width, height, length), //right top front height9
//BOTTOM FACE
new Vector3(-width, -height, length), //left bottom front 20
new Vector3(width, -height, length), //right bottom front 2height
new Vector3(-width, -height, -length), //left bottom back 22
new Vector3(width, -height, -length), //right bottom back 2width
};
//triangles// 3 points clockwise determines which side is visible
int[] triangles = new int[]
{
//front face
0,
2,
3, //first triangle
3,
1,
0, //second triangle
//back face
4,
6,
7, //first triangle
7,
5,
4, //second triangle
//left face
8,
10,
11, //first triangle
11,
9,
8, //second triangle
//right face
12,
14,
15, //first triangle
15,
13,
12, //second triangle
//top face
16,
18,
19, //first triangle
19,
17,
16, //second triangle
//bottom face
20,
22,
23, //first triangle
23,
21,
20 //second triangle
};
//UVs
Vector2[] uvs1 = new Vector2[]
{
//front face// 0,0 is bottom left, 1,1 is top right
new Vector2(0, 1),
new Vector2(0, 0),
new Vector2(1, 1),
new Vector2(1, 0),
new Vector2(0, 1),
new Vector2(0, 0),
new Vector2(1, 1),
new Vector2(1, 0),
new Vector2(0, 1),
new Vector2(0, 0),
new Vector2(1, 1),
new Vector2(1, 0),
new Vector2(0, 1),
new Vector2(0, 0),
new Vector2(1, 1),
new Vector2(1, 0),
new Vector2(0, 1),
new Vector2(0, 0),
new Vector2(1, 1),
new Vector2(1, 0),
new Vector2(0, 1),
new Vector2(0, 0),
new Vector2(1, 1),
new Vector2(1, 0)
};
mesh1.Clear();
mesh1.vertices = vertices;
mesh1.triangles = triangles;
mesh1.uv = uvs1;
mesh1.RecalculateNormals();
}
// Update is called once per frame
void Update()
{
cube();
}
}
You need to use inheritance.
Make a class Cube like this:
public class Cube:MonoBehaviour{
}
Then make other classes like this:
public class Door:Cube{
}
You can get more details here: https://unity3d.com/learn/tutorials/topics/scripting/inheritance
You don't really need to program the dimensions of a cube or other elements in your scene from scratch. Unity already offers some primitives you can instantiate in your game, and access their attributes from your script to modify their values.
In case you want to create an Enviroment programatically using GameObjects with primitives ( like cubes, spheres...) or custom GameObjects (like 3D models you created on Blender) you can do something like this:
//You will need to pass in the inspector a GameObject as parameter in the correct field
public GameObject customGameObject;
void Start()
{
generateEnviroment()
}
void generateEnviroment()
{
//You instantiate a GameObject of type cube
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
//You change its position
cube.transform.position = new Vector3(0, 0.5F, 0);
// Widen the object by 0.1
cube.transform.localScale += new Vector3(0.1F, 0, 0);
//Change material properties, assuming it has a material component
Renderer rend = cube.GetComponent<Renderer>();
rend.material.shader = Shader.Find("Specular");
rend.material.SetColor("_SpecColor", Color.red);
//In case you want to add other type of GameObject, like a car or sth you have created:
GameObject myGameObject = GameObject.Instantiate (customGameObject);
}
You can make that function as long as complex as you want, just being tidy with names.
https://docs.unity3d.com/ScriptReference/GameObject.CreatePrimitive.html
In System.Drawing and System.Drawing.Drawing2D, I can only draw horizontal or vertical shape. Now i want to draw custom shape.
Given the coordinate of points A, B, C, D. I want to draw an ellipse like the blue one in the picture.
The example below is taken from MSDN:
private void RotateTransformAngle(PaintEventArgs e)
{
// Set world transform of graphics object to translate.
e.Graphics.TranslateTransform(100.0F, 0.0F);
// Then to rotate, prepending rotation matrix.
e.Graphics.RotateTransform(30.0F);
// Draw rotated, translated ellipse to screen.
e.Graphics.DrawEllipse(new Pen(Color.Blue, 3), 0, 0, 200, 80);
}
The correct solution involves:
Calculating the center
using Graphics.TranslateTransform to move the center to the origin
Calculating the Size and the Location of the bounding Rectangle
using Graphics.RotateTransform to rotate the canvas
Drawing the ellipse with Graphics.DrawEllipse
Resetting the Graphcis object
This does take a little Math but will produce real and fine ellipses..
For fun you also may want to play with a cheap, fake solution: I uses the DrawClosedCurve method with a tension.
To test I added a TrackBar set with a Maximum of 100.
Values of around 80, i.e. Tensions of around 0.8f create pretty nice ellipsoids:
private void panel1_Paint(object sender, PaintEventArgs e)
{
List<Point> points1 = new List<Point>()
{ new Point(300, 100), new Point(500, 300), new Point(400, 500), new Point(200, 300) };
List<Point> points2 = new List<Point>()
{ new Point(100, 100), new Point(500, 100), new Point(500, 400), new Point(100, 400) };
e.Graphics.DrawClosedCurve(Pens.Red, points1.ToArray(),
(float)(trackBar1.Value / 100f), System.Drawing.Drawing2D.FillMode.Alternate);
e.Graphics.DrawClosedCurve(Pens.Blue, points2.ToArray(),
(float)(trackBar1.Value / 100f), System.Drawing.Drawing2D.FillMode.Alternate);
}
How do you draw shapes, such as Rectangles and Circles, in MonoGame without having to save the a predrawn shape in the Content folder?
DrawRectangle() and DrawEllipse() are for Windows Form and do not work in OpenGL, which is what I am using.
Use 3D primitives and a 2D projection
Here's a simple example with explanations
I define a 10x10 rectangle and set the world matrix to make it look like a 2D projection :
Note : the BasicEffect is what draws your primitive
protected override void LoadContent()
{
_vertexPositionColors = new[]
{
new VertexPositionColor(new Vector3(0, 0, 1), Color.White),
new VertexPositionColor(new Vector3(10, 0, 1), Color.White),
new VertexPositionColor(new Vector3(10, 10, 1), Color.White),
new VertexPositionColor(new Vector3(0, 10, 1), Color.White)
};
_basicEffect = new BasicEffect(GraphicsDevice);
_basicEffect.World = Matrix.CreateOrthographicOffCenter(
0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, 0, 0, 1);
}
Then I draw the whole thing :D
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
EffectTechnique effectTechnique = _basicEffect.Techniques[0];
EffectPassCollection effectPassCollection = effectTechnique.Passes;
foreach (EffectPass pass in effectPassCollection)
{
pass.Apply();
GraphicsDevice.DrawUserPrimitives(PrimitiveType.LineStrip, _vertexPositionColors, 0, 4);
}
base.Draw(gameTime);
}
There you have your rectangle !
Now this is just the tip the of the iceberg,
To draw filled rectangles : draw 2 triangle primitives
For an ellipse/circle see these : Draw an Ellipse in XNA and Draw simple circle in XNA
Or as mentioned in one of the posts above you could use a shader that does it instead ...
I needed to draw a Superellipse a while ago and ended up sketching this shader :
Drawing a SuperEllipse in HLSL
As you can see in the post a Superellipse not only draws ellipse but also other shapes and maybe even circles (I did not test) so you might be interested in it.
Ultimately you will want some class/methods to hide all these details so you just have to invoke something like DrawCircle().
Tip : by posting # https://gamedev.stackexchange.com/ you will likely get more answers for Monogame-related questions
:D
If you need to create a rectangle in 2D you can just do this:
Color[] data = new Color[rectangle.Width * rectangle.Height];
Texture2D rectTexture = new Texture2D(GraphicsDevice, rectangle.Width, rectangle.Height);
for (int i = 0; i < data.Length; ++i)
data[i] = Color.White;
rectTexture.SetData(data);
var position = new Vector2(rectangle.Left, rectangle.Top);
spriteBatch.Draw(rectTexture, position, Color.White);
Might be a tad bit easier than Aybe's answer in some situations. This creates a solid rectangle.
I found a simple solution for drawing filled and non-filled shapes, I don't know if it's power consuming or not, but here it is anyway:
{
//Filled
Texture2D _texture;
_texture = new Texture2D(graphicsDevice, 1, 1);
_texture.SetData(new Color[] { Color.White });
spriteBatch.Draw(_texture, Rect, Color.White);
}
{
//Non filled
Texture2D _texture;
_texture = new Texture2D(graphicsDevice, 1, 1);
_texture.SetData(new Color[] { Color.White });
spriteBatch.Draw(_texture, new Rectangle(Rect.Left, Rect.Top, Rect.Width, 1), Color.White);
spriteBatch.Draw(_texture, new Rectangle(Rect.Right, Rect.Top, 1, Rect.Height), Color.White);
spriteBatch.Draw(_texture, new Rectangle(Rect.Left, Rect.Bottom, Rect.Width, 1), Color.White);
spriteBatch.Draw(_texture, new Rectangle(Rect.Left, Rect.Top, 1, Rect.Height), Color.White);
}
I have drawn vertical Rectangle but i want to fill it from bottom to top.
here is the code i used
System.Drawing.Drawing2D.LinearGradientBrush linGrBrush =
new System.Drawing.Drawing2D.LinearGradientBrush(
new Point(0, 12),
new Point(0,2),
Color.FromArgb(0, 0, 0, 0),
Color.FromArgb(255, 190, 0, 0));
Pen pen = new Pen(linGrBrush);
e.Graphics.FillRectangle(linGrBrush,groupBox2.Width -50,10, 25, x);
using (Pen Pen1 = new Pen(Color.BurlyWood, 4))
{
e.Graphics.DrawRectangle(Pen1, groupBox2.Width -50,10, 25, 200);
}
x is color fill offset which fill is used to fill rectangle after every 2 seconds.
I think that you should adjust the starting and the ending points of the gradient:
System.Drawing.Drawing2D.LinearGradientBrush linGrBrush =
new System.Drawing.Drawing2D.LinearGradientBrush(
new Point(0, 1),
new Point(0,0),
Color.FromArgb(0, 0, 0, 0),
Color.FromArgb(255, 190, 0, 0));