How can i change camera3d movement speed in raylib - c++

im a 13 y/o Moroccan programmer and im in a bit of a sticky situation
so im trying to make a first person game so i used raylib since it is the easiest way to do so without using an engine,i wrote the code and stuff and it worked,one problem tho,it was extremely slow so can anyone help me?
here is the code btw:
#include "raylib.h"
int main()
{
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window");
float cx = 0.0f;
float cy = 10.0f;
float cz = 10.0f;
Camera3D camera = { 0 };
camera.position = (Vector3){ cx,cy,cz }; // Camera position
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE;
SetCameraMode(camera,CAMERA_FIRST_PERSON); // Camera mode type
Vector3 cubepos = {0.0f,1.0f,0.0f};
SetTargetFPS(60);
while (!WindowShouldClose())
{
UpdateCamera(&camera);
BeginDrawing();
ClearBackground(BLACK);
BeginMode3D(camera);
DrawCube(cubepos,3.0f,3.0f,3.0f,RED);
EndMode3D();
EndDrawing();
}
CloseWindow();
return 0;
}

Looking at the Raylib's UpdateCamera(Camera*) function at https://github.com/raysan5/raylib/blob/master/src/rcamera.h, we shall change a bit.
First copy and paste the rcamera.h into your project directory.
At the beginning of the file add the line #define CAMERA_IMPLEMENTATION
Include the file in your main.cpp after the line ``#include <raylib.h>`
Laslty, in your rcamera.h, change the #define PLAYER_MOVEMENT_SENSITIVITY 2.0f to how much ever you want.
If you face C to C++ conversion issues, particularly in line 220-229, you should replace to:
static CameraData CAMERA = { // Global CAMERA state context
0,
0,
1.85f,
{ 0 },
{ 'W', 'S', 'D', 'A', 'E', 'Q' },
341, // raylib: KEY_LEFT_CONTROL
342, // raylib: KEY_LEFT_ALT
2 // raylib: MOUSE_BUTTON_MIDDLE
};
You can remove some of the uneeded switch cases (Line 306-405 and 495-592) to increase performane.

Related

How to check if ball colides with edge of window in c++ with raylib

i am new to raylib and wanted to make a little 2d ball thing, and i don't know how to stop the sprite from going of the screen, it only works with 2 edges and not the others, would anybody please help?
My C++ file:
game.cpp:
#include <raylib.h>
int main() {
InitWindow(800, 600, "My Game!");
// Vector2 ballPosition = {400.0f, 300.0f};
Vector2 ballPosition = { (float)800/2, (float)600/2 };
SetTargetFPS(60);
while(!WindowShouldClose()) {
if (IsKeyDown(KEY_RIGHT)) ballPosition.x += 2.0f;
if (IsKeyDown(KEY_LEFT)) ballPosition.x -= 2.0f;
if (IsKeyDown(KEY_UP)) ballPosition.y -= 2.0f;
if (IsKeyDown(KEY_DOWN)) ballPosition.y += 2.0f;
DrawText("move the ball with arrow keys", 10, 10, 20, DARKGRAY);
Texture2D ball = LoadTexture("ball.png");
DrawTexture(ball, ballPosition.x - 50, ballPosition.y - 50, WHITE);
if (ballPosition.x < 0) ballPosition.x = 0;
if (ballPosition.x > 800) ballPosition.x = 800;
if (ballPosition.y < 0) ballPosition.y = 0;
if (ballPosition.y > 600) ballPosition.y = 600;
BeginDrawing();
ClearBackground(RAYWHITE);
// Vector2 mousePosition = GetMousePosition();
// ballPosition = mousePosition;
// DrawCircleV(ballPosition, 20.0f, BLUE);
EndDrawing();
}
CloseWindow();
return 0;
}
Took me a while but your problem is a combination of the offset for drawing the ball texture and how you check for the bounds of the screen (assuming the image is a 50x50, you didn't specify).
Notice I've locally added a circle directly at the ballposition (right after the DrawTextureCall):
DrawCircleV(ballPosition, 2.0f, MAROON);
Since this is to the right and bottom of the image, your bounds check will only be correct for the right and bottom edges. For the left and top edges the entire image disappears before the ballposition hits the edge.
In my opinion you should draw the image at the ballposition and adjust the bounds check to take the image size into account:
const float ballHalfSize = ball.width / 2.0f; // assuming square image
DrawTexture(ball, int(ballPosition.x - ballHalfSize), int(ballPosition.y - ballHalfSize), WHITE);
if ((ballPosition.x - ballHalfSize) < 0) ballPosition.x = ballHalfSize;
if ((ballPosition.x + ballHalfSize) > 800) ballPosition.x = 800 - ballHalfSize;
if ((ballPosition.y - ballHalfSize) < 0) ballPosition.y = ballHalfSize;
if ((ballPosition.y + ballHalfSize) > 600) ballPosition.y = 600 - ballHalfSize;
With this new version I get correct collision behavior on all 4 edges of the screen.

Rendering FreeType fonts

I have been trying to render FreeType2 fonts in OpenGL 3. I used NeHe's tutorial http://nehe.gamedev.net/tutorial/freetype_fonts_in_opengl/24001/ . however, I modified it a little for modern OpenGL 3+. Actually, I use glBufferData(...,GL_DYNAMIC_DRAW) to update vertex buffer for every character. The arrays of vertices are created during glyph loading as NeHe does with display lists:
int width = next_p2(bitmap.width);
int height = next_p2(bitmap.rows);
float x=(float)bitmap.width / (float)width,
y= (float)bitmap.rows / (float)height;
using namespace glm;
glyphsVertices[c] = new pxgVertex2dT[4];
glyphsVertices[c][0] = { vec2(0,bitmap.rows), vec2(0,y) };
glyphsVertices[c][1] = { vec2(0,0), vec2(0,0) };
glyphsVertices[c][2] = { vec2(bitmap.width,0), vec2(x,0) };
glyphsVertices[c][3] = { vec2(bitmap.width,bitmap.rows), vec2(x,y) };
Where glyphVertices is two-dimentional array of such structure:
struct Vertex2dT
{
glm::vec2 pos;
glm::vec2 texCoord;
};
Unfortunately, I get the following result:
So, what am I doing wrong?
As SAKrisT correctly pointed out, the problem was caused by incorrect offset by Y axis. Playing a bit with the code, I figured out the solution:
if(FT_Load_Char(face, c, FT_LOAD_RENDER))
return;
FT_GlyphSlot g = face->glyph;
int width = next_p2(g->bitmap.width);
int height = next_p2(g->bitmap.rows);
...
float x=(float)g->bitmap.width / (float)width,
y= (float)g->bitmap.rows / (float)height;
float x2 = g->bitmap_left;
float y2 = g->bitmap_top;
float w = g->bitmap.width;
float h = g->bitmap.rows;
using namespace glm;
glyphsVertices[c] = new pxgVertex2dT[4];
glyphsVertices[c][0] = { vec2(0,h-y2), vec2(0,y) };
glyphsVertices[c][1] = { vec2(0,-y2), vec2(0,0) };
glyphsVertices[c][2] = { vec2(w,-y2), vec2(x,0) };
glyphsVertices[c][3] = { vec2(w,h-y2), vec2(x,y) };
Now it works perfectly!
Two things happening: Your code assumes the origin of the viewport in the upper left, while in reality it's in the lower left, which means your image is vertically flipped.
FreeType renders the glyph images with the origin in the upper left as well, which counters the y-flip of the geometry, hence the characters look upright.

DirectX9 moving a camera left and right

According to this site: http://www.directxtutorial.com/Lesson.aspx?lessonid=9-4-5
3DXMATRIX* D3DXMATRIXLookAtLH(D3DXMATRIX* pOut,
CONST D3DXVECTOR3* pEye,
CONST D3DXVECTOR3* pAt,
CONST D3DXVECTOR3* pUp);
D3DXMATRIX* pOut,
// We know this one. It is the pointer to the matrix we are going to fill.
CONST D3DXVECTOR3* pEye,
// This parameter is a pointer to a vector which contains the exact position
// of the camera. Considering our example above, we want to fill this struct
// with (100, 100, 100).
CONST D3DXVECTOR3* pAt,
// This vector contains the exact location the camera should look at.
// Our example is looking at (0, 0, 0), so we will fill this struct
// with those values.
CONST D3DXVECTOR3* pUp,
// This vector contains the direction of "up" for the camera. In other
// words, what direction will the top of the screen be. Usually, game
// programmers use the y-axis as the "up" direction. To set the camera
// this way, you simply need to fill this struct with (0, 1, 0), or
// 1.0f on the y-axis and 0.0f on the other two.
I would assume that all I would have to do is change the x coord of pEye, and pAt plus/minus to move left and right. However, when I do this, funky things happen. Is there anything I am doing wrong? Below is my code!
void world_view::start_cam() {
vPosition = D3DXVECTOR3 ( console_editor.window_w/2 , console_editor.window_h/2 , console_editor.window_h/2 );
vLookAt = D3DXVECTOR3 ( console_editor.window_w/2 , console_editor.window_h/2 , 0.0f );
vUp = D3DXVECTOR3 ( 0.0f , -1.0f , 0.0f );
fov = D3DXToRadian(90); // the horizontal field of view
aspectRatio = (FLOAT)console_editor.window_w / (FLOAT)console_editor.window_h; // aspect ratio
zNear = 1.0f;
zFar = console_editor.window_h/2+10;
}
void world_view:: MoveLeft(float units) {
}
void world_view:: MoveRight(float units) {
D3DXVECTOR3 vTemp = struct_world_view.vPosition;
vTemp.x = vTemp.x + units;
//vTemp.y = vTemp.y + units;
//vTemp.z = vTemp.z + units;
struct_world_view.vPosition = vTemp;
D3DXVECTOR3 vlTemp = struct_world_view.vLookAt;
vlTemp.x + units;
//vlTemp.y + units;
//vlTemp.z + units;
struct_world_view.vLookAt = vlTemp;
}
void world_view::UpdateCamera(){
D3DXMatrixLookAtLH(&struct_world_view.cam,
&struct_world_view.vPosition,
&struct_world_view.vLookAt,
&struct_world_view.vUp);
D3DXMatrixPerspectiveFovLH(&struct_world_view.cam_lens,
struct_world_view.fov,
struct_world_view.aspectRatio,
struct_world_view.zNear,
struct_world_view.zFar);
}
![Before][1]![After][2]
This is an example of Before and After moving right. Any clarification would greatly help!
Move both the position of the camera and where it's looking:
void world_view:: MoveRight(float units) {
struct_world_view.vLookAt.x += units;
struct_world_view.vPosition.x += units;
}
Edit: also - if you only want to be able to move right, you may want to check for negative units.

OpenGL Camera vectors

I have a very rudimentary camera which generates 3 vectors for use with gluLookAt(...) the problem is I'm not sure if this is correct, I adapted code from something my lecturer showed us (I think he got it from somewhere).
This actually works until you spin the mouse round in circles than camera starts to rotate around the z-axis. Which shouldn't happen as the mouse coords are only attached to the pitch and yaw not the roll.
Camera
// Camera.hpp
#ifndef MOOT_CAMERA_INCLUDE_HPP
#define MOOT_CAMERA_INCLUDE_HPP
#include <GL/gl.h>
#include <GL/glu.h>
#include <boost/utility.hpp>
#include <Moot/Platform.hpp>
#include <Moot/Vector3D.hpp>
namespace Moot
{
class Camera : public boost::noncopyable
{
protected:
Vec3f m_position, m_up, m_right, m_forward, m_viewPoint;
uint16_t m_height, m_width;
public:
Camera()
{
m_forward = Vec3f(0.0f, 0.0f, -1.0f);
m_right = Vec3f(1.0f, 0.0f, 0.0f);
m_up = Vec3f(0.0f, 1.0f, 0.0f);
}
void setup(uint16_t setHeight, uint16_t setWidth)
{
m_height = setHeight;
m_width = setWidth;
}
void move(float distance)
{
m_position += (m_forward * distance);
}
void addPitch(float setPitch)
{
m_forward = (m_forward * cos(setPitch) + (m_up * sin(setPitch)));
m_forward.setNormal();
// Cross Product
m_up = (m_forward / m_right) * -1;
}
void addYaw(float setYaw)
{
m_forward = ((m_forward * cos(setYaw)) - (m_right * sin(setYaw)));
m_forward.setNormal();
// Cross Product
m_right = m_forward / m_up;
}
void addRoll(float setRoll)
{
m_right = (m_right * cos(setRoll) + (m_up * sin(setRoll)));
m_right.setNormal();
// Cross Product
m_up = (m_forward / m_right) * -1;
}
virtual void apply() = 0;
}; // Camera
} // Moot
#endif
Snippet from update cycle
// Mouse movement
m_camera.addPitch((float)input().mouseDeltaY() * 0.001);
m_camera.addYaw((float)input().mouseDeltaX() * 0.001);
apply() in the camera class is defined in an inherited class, which is called from the draw function of the game loop.
void apply()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(40.0,(GLdouble)m_width/(GLdouble)m_height,0.5,20.0);
m_viewPoint = m_position + m_forward;
gluLookAt( m_position.getX(), m_position.getY(), m_position.getZ(),
m_viewPoint.getX(), m_viewPoint.getY(), m_viewPoint.getZ(),
m_up.getX(), m_up.getY(), m_up.getZ());
}
Don't accumulate the transforms in your vectors, store the angles and generate the vectors on-the-fly.
EDIT: Floating-point stability. Compare the output of a and b:
#include <iostream>
using namespace std;
int main()
{
const float small = 0.00001;
const unsigned int times = 100000;
float a = 0.0f;
for( unsigned int i = 0; i < times; ++i )
{
a += small;
}
cout << a << endl;
float b = 0.0f;
b = small * times;
cout << b << endl;
return 0;
}
Output:
1.00099
1
I am not sure where to start, as you are posting only small snippets, not enough to fully reproduce the problem.
In your methods you update all parameters, and your parameters are depending on previous values. I am not sure what exactly you call, because you posted that you call only these two :
m_camera.addPitch((float)input().mouseDeltaY() * 0.001);
m_camera.addYaw((float)input().mouseDeltaX() * 0.001);
You should somehow break that circle by adding new parameters, and the output should depend on the input (for example, m_position shouldn't depend on m_forward).
You should also initialize all variables in the constructor, and I see you are initializing only m_forward, m_right and m_up (by the way, use initialization list).
You might want to reconsider your approach in favor of using quaternion rotations as described in this paper. This has the advantage of representing all of your accumulated rotations as a single rotation about a single vector (only need to keep track of a single quaternion) which you can apply to the canonical orientation vectors (up, norm and right) describing the camera orientation. Furthermore, since you're using C++, you can use the Boost quaternion class to manage the math of most of it.

How do I draw lines using XNA?

I've read a bunch of tutorials involving XNA (and it's various versions) and I still am a little confused on drawing primitives. Everything seems to be really convoluted.
Can someone show me, using code, the simplest XNA implementation of drawing one or two lines on to the screen? Perhaps with a brief explanation (including the boilerplate)?
I'm not a games programmer and I have little XNA experience. My ultimate goal is to draw some lines onto the screen which I will eventually transform with rotations, etc (by hand). However, for this first step.. I need to simply draw the lines! I remember back in my ancient OpenGL days it was fairly straightforward when drawing a line with a few method calls. Should I simply revert to using unmanaged directx calls?
When working with XNA, everything (even 2d primitives) have to be expressed in a way that a 3d card can understand, which means that a line is just a set of vertices.
MSDN has a pretty good walkthrough here:
http://msdn.microsoft.com/en-us/library/bb196414.aspx#ID2EEF
You'll find that it takes more code to render a primitive line than it would take to just setup a textured quad and rotate that, since in essence, your doing the same thing when rendering a line.
Following NoHayProblema's answer (I cannot comment yet).
That answer, although the correct one for this old question, is incomplete. Texture2D constructor returns an uninitialized texture, which is never painted on screen.
In order to use that approach, you need to set the texture's data like this:
Texture2D SimpleTexture = new Texture2D(GraphicsDevice, 1, 1, false,
SurfaceFormat.Color);
Int32[] pixel = {0xFFFFFF}; // White. 0xFF is Red, 0xFF0000 is Blue
SimpleTexture.SetData<Int32> (pixel, 0, SimpleTexture.Width * SimpleTexture.Height);
// Paint a 100x1 line starting at 20, 50
this.spriteBatch.Draw(SimpleTexture, new Rectangle(20, 50, 100, 1), Color.Blue);
Take into account that the way you write the data into pixel must be consistent with the texture's SurfaceFormat. The example works because the texture is being formatted as RGB.
Rotations can be applied in spriteBatch.Draw like this:
this.spriteBatch.Draw (SimpleTexture, new Rectangle(0, 0, 100, 1), null,
Color.Blue, -(float)Math.PI/4, new Vector2 (0f, 0f), SpriteEffects.None, 1f);
found a tutorial for that
http://www.bit-101.com/blog/?p=2832
its using a BasicEffect (shader)
and the built in draw user primitive in XNA 4.0
some code samples i find helpful:
load content method
basicEffect = new BasicEffect(GraphicsDevice);
basicEffect.VertexColorEnabled = true;
basicEffect.Projection = Matrix.CreateOrthographicOffCenter
(0, GraphicsDevice.Viewport.Width,     // left, right
GraphicsDevice.Viewport.Height, 0,    // bottom, top
0, 1);   
draw method
basicEffect.CurrentTechnique.Passes[0].Apply();
var vertices = new VertexPositionColor[4];
vertices[0].Position = new Vector3(100, 100, 0);
vertices[0].Color = Color.Black;
vertices[1].Position = new Vector3(200, 100, 0);
vertices[1].Color = Color.Red;
vertices[2].Position = new Vector3(200, 200, 0);
vertices[2].Color = Color.Black;
vertices[3].Position = new Vector3(100, 200, 0);
vertices[3].Color = Color.Red;
GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.LineList, vertices, 0, 2);
have fun and vote up if this helped you. also pay a visit to the tutorial i got this from.
Well, you can do it in a very simple way without getting into the 3D horrible vector stuff.
Just create a quick texture, for example:
Texture2D SimpleTexture = new Texture2D(GraphicsDevice, 1, 1, false, SurfaceFormat.Color);
And then just draw a line using that texture:
this.spriteBatch.Draw(SimpleTexture, new Rectangle(100, 100, 100, 1), Color.Blue);
I hope this helps
The simplest best way, I think, is to get the image of just a white pixel then stretch that pixel in a rectangle to look like a line
I made a Line class,
class Line
{
Texture pixel = ((set this to a texture of a white pixel with no border));
Vector2 p1, p2; //this will be the position in the center of the line
int length, thickness; //length and thickness of the line, or width and height of rectangle
Rectangle rect; //where the line will be drawn
float rotation; // rotation of the line, with axis at the center of the line
Color color;
//p1 and p2 are the two end points of the line
public Line(Vector2 p1, Vector2 p2, int thickness, Color color)
{
this.p1 = p1;
this.p2 = p2;
this.thickness = thickness;
this.color = color;
}
public void Update(GameTime gameTime)
{
length = (int)Vector2.Distance(p1, p2); //gets distance between the points
rotation = getRotation(p1.X, p1.Y, p2.X, p2.Y); //gets angle between points(method on bottom)
rect = new Rectangle((int)p1.X, (int)p1.Y, length, thickness)
//To change the line just change the positions of p1 and p2
}
public void Draw(SpriteBatch spriteBatch, GameTime gameTime)
{
spriteBatch.Draw(pixel, rect, null, color, rotation, new Vector2.Zero, SpriteEffects.None, 0.0f);
}
//this returns the angle between two points in radians
private float getRotation(float x, float y, float x2, float y2)
{
float adj = x - x2;
float opp = y - y2;
float tan = opp / adj;
float res = MathHelper.ToDegrees((float)Math.Atan2(opp, adj));
res = (res - 180) % 360;
if (res < 0) { res += 360; }
res = MathHelper.ToRadians(res);
return res;
}
Hope this helps
There is also the "round line" code that "manders" has released on CodePlex:
http://roundline.codeplex.com/
Here is the blog post about it:
XNA RoundLine Code Released on CodePlex
Just stretch a white pixel.
point = game.Content.Load<Texture2D>("ui/point");
public void DrawLine(Vector2 start, Vector2 end, Color color)
{
Vector2 edge = end - start;
float angle = (float)Math.Atan2(edge.Y, edge.X);
spriteBatch.Begin();
spriteBatch.Draw(point,
new Rectangle((int)start.X, (int)start.Y, (int)edge.Length(), 1),
null,
color,
angle,
new Vector2(0, 0),
SpriteEffects.None,
0);
spriteBatch.End();
}
I wanted to draw rays so that I could debug rays created by explosions and where they intersect objects. This will draw a single pixel thin line between two points. This is what I did:
Class to store some simple ray data. The XNA default ray class could work, but it doesn't store the length of the ray to intersection.
public class myRay
{
public Vector3 position, direction;
public float length;
}
A list to store the rays that are to be drawn:
List<myRay> DebugRays= new List<myRay>();
Create a BasicEffect and pass it a "Matrix.CreateOrthographicOffCenter" projection with your desired resolution in the LoadContent method.
Then run this in the draw method:
private void DrawRays()
{
spriteBatch.Begin();
foreach (myRay ray in DebugRays)
{
//An array of 2 vertices - a start and end position
VertexPositionColor[] Vertices = new VertexPositionColor[2];
int[] Indices = new int[2];
//Starting position of the ray
Vertices[0] = new VertexPositionColor()
{
Color = Color.Orange,
Position = ray.position
};
//End point of the ray
Vertices[1] = new VertexPositionColor()
{
Color = Color.Orange,
Position = ray.position + (ray.direction * ray.length)
};
Indices[0] = 0;
Indices[1] = 1;
foreach (EffectPass pass in BasicEffect.CurrentTechnique.Passes)
{
pass.Apply();
GraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.LineStrip, Vertices, 0, 2, Indices, 0, 1, VertexPositionColorTexture.VertexDeclaration);
}
}
spriteBatch.End();
}
So when an explosion happens in my game it does this (Psuedocode):
OnExplosionHappened()
{
DebugRays.Clear()
myRay ray = new myRay()
{
position = explosion.Position,
direction = GetDirection(explosion, solid),
//Used GetValueOrDefault here to prevent null value errors
length = explosionRay.Intersects(solid.BoundingBox).GetValueOrDefault()
};
DebugRays.Add(ray);
}
It's pretty simple (It possibly looks way more complicated than it is) and it'd be easy to put it into a separate class that you never have to think about again. It also lets you draw a whole lot of lines at once.
I encountered this problem my self and decided to make a class called LineBatch.
LineBatch will draw lines without needing a spriteBatch or dots.
The class is below.
public class LineBatch
{
bool cares_about_begin_without_end;
bool began;
GraphicsDevice GraphicsDevice;
List<VertexPositionColor> verticies = new List<VertexPositionColor>();
BasicEffect effect;
public LineBatch(GraphicsDevice graphics)
{
GraphicsDevice = graphics;
effect = new BasicEffect(GraphicsDevice);
Matrix world = Matrix.Identity;
Matrix view = Matrix.CreateTranslation(-GraphicsDevice.Viewport.Width / 2, -GraphicsDevice.Viewport.Height / 2, 0);
Matrix projection = Matrix.CreateOrthographic(GraphicsDevice.Viewport.Width, -GraphicsDevice.Viewport.Height, -10, 10);
effect.World = world;
effect.View = view;
effect.VertexColorEnabled = true;
effect.Projection = projection;
effect.DiffuseColor = Color.White.ToVector3();
cares_about_begin_without_end = true;
}
public LineBatch(GraphicsDevice graphics, bool cares_about_begin_without_end)
{
this.cares_about_begin_without_end = cares_about_begin_without_end;
GraphicsDevice = graphics;
effect = new BasicEffect(GraphicsDevice);
Matrix world = Matrix.Identity;
Matrix view = Matrix.CreateTranslation(-GraphicsDevice.Viewport.Width / 2, -GraphicsDevice.Viewport.Height / 2, 0);
Matrix projection = Matrix.CreateOrthographic(GraphicsDevice.Viewport.Width, -GraphicsDevice.Viewport.Height, -10, 10);
effect.World = world;
effect.View = view;
effect.VertexColorEnabled = true;
effect.Projection = projection;
effect.DiffuseColor = Color.White.ToVector3();
}
public void DrawAngledLineWithRadians(Vector2 start, float length, float radians, Color color)
{
Vector2 offset = new Vector2(
(float)Math.Sin(radians) * length, //x
-(float)Math.Cos(radians) * length //y
);
Draw(start, start + offset, color);
}
public void DrawOutLineOfRectangle(Rectangle rectangle, Color color)
{
Draw(new Vector2(rectangle.X, rectangle.Y), new Vector2(rectangle.X + rectangle.Width, rectangle.Y), color);
Draw(new Vector2(rectangle.X, rectangle.Y), new Vector2(rectangle.X, rectangle.Y + rectangle.Height), color);
Draw(new Vector2(rectangle.X + rectangle.Width, rectangle.Y), new Vector2(rectangle.X + rectangle.Width, rectangle.Y + rectangle.Height), color);
Draw(new Vector2(rectangle.X, rectangle.Y + rectangle.Height), new Vector2(rectangle.X + rectangle.Width, rectangle.Y + rectangle.Height), color);
}
public void DrawOutLineOfTriangle(Vector2 point_1, Vector2 point_2, Vector2 point_3, Color color)
{
Draw(point_1, point_2, color);
Draw(point_1, point_3, color);
Draw(point_2, point_3, color);
}
float GetRadians(float angleDegrees)
{
return angleDegrees * ((float)Math.PI) / 180.0f;
}
public void DrawAngledLine(Vector2 start, float length, float angleDegrees, Color color)
{
DrawAngledLineWithRadians(start, length, GetRadians(angleDegrees), color);
}
public void Draw(Vector2 start, Vector2 end, Color color)
{
verticies.Add(new VertexPositionColor(new Vector3(start, 0f), color));
verticies.Add(new VertexPositionColor(new Vector3(end, 0f), color));
}
public void Draw(Vector3 start, Vector3 end, Color color)
{
verticies.Add(new VertexPositionColor(start, color));
verticies.Add(new VertexPositionColor(end, color));
}
public void End()
{
if (!began)
if (cares_about_begin_without_end)
throw new ArgumentException("Please add begin before end!");
else
Begin();
if (verticies.Count > 0)
{
VertexBuffer vb = new VertexBuffer(GraphicsDevice, typeof(VertexPositionColor), verticies.Count, BufferUsage.WriteOnly);
vb.SetData<VertexPositionColor>(verticies.ToArray());
GraphicsDevice.SetVertexBuffer(vb);
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Apply();
GraphicsDevice.DrawPrimitives(PrimitiveType.LineList, 0, verticies.Count / 2);
}
}
began = false;
}
public void Begin()
{
if (began)
if (cares_about_begin_without_end)
throw new ArgumentException("You forgot end.");
else
End();
verticies.Clear();
began = true;
}
}
Here is a simple way that I use to make lines by specifying a start coordinate, an end coordinate, width, and color of them:
NOTE: you must add a file named "dot" to the content directory (the line will be made out of these).
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;
namespace Xna.LineHelper
{
public class LineManager
{
int loopCounter;
int lineLegnth;
Vector2 lineDirection;
Vector2 _position;
Color dotColor;
Rectangle _rectangle;
List<Texture2D> _dots = new List<Texture2D>();
FunctionsLibrary functions = new FunctionsLibrary();
public void CreateLineFiles(Vector2 startPosition, Vector2 endPosition, int width, Color color, ContentManager content)
{
dotColor = color;
_position.X = startPosition.X;
_position.Y = startPosition.Y;
lineLegnth = functions.Distance((int)startPosition.X, (int)endPosition.X, (int)startPosition.Y, (int)endPosition.Y);
lineDirection = new Vector2((endPosition.X - startPosition.X) / lineLegnth, (endPosition.Y - startPosition.Y) / lineLegnth);
_dots.Clear();
loopCounter = 0;
_rectangle = new Rectangle((int)startPosition.X, (int)startPosition.Y, width, width);
while (loopCounter < lineLegnth)
{
Texture2D dot = content.Load<Texture2D>("dot");
_dots.Add(dot);
loopCounter += 1;
}
}
public void DrawLoadedLine(SpriteBatch sb)
{
foreach (Texture2D dot in _dots)
{
_position.X += lineDirection.X;
_position.Y += lineDirection.Y;
_rectangle.X = (int)_position.X;
_rectangle.Y = (int)_position.Y;
sb.Draw(dot, _rectangle, dotColor);
}
}
}
public class FunctionsLibrary
{
//Random for all methods
Random Rand = new Random();
#region math
public int TriangleArea1(int bottom, int height)
{
int answer = (bottom * height / 2);
return answer;
}
public double TriangleArea2(int A, int B, int C)
{
int s = ((A + B + C) / 2);
double answer = (Math.Sqrt(s * (s - A) * (s - B) * (s - C)));
return answer;
}
public int RectangleArea(int side1, int side2)
{
int answer = (side1 * side2);
return answer;
}
public int SquareArea(int side)
{
int answer = (side * side);
return answer;
}
public double CircleArea(int diameter)
{
double answer = (((diameter / 2) * (diameter / 2)) * Math.PI);
return answer;
}
public int Diference(int A, int B)
{
int distance = Math.Abs(A - B);
return distance;
}
#endregion
#region standardFunctions
public int Distance(int x1, int x2, int y1, int y2)
{
return (int)(Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));
}
#endregion
}
}