I am currently making a golf ball game using C# and XNA.
So far I have been able to make the ball fly, bounce, and roll, while displaying the position and velocity.
Now I want to be able to see the ball path (similar to images below), in order to check the whole ball movement.
http://www.golf-simulators.com/images/ms4.jpg
My code updates the ball position at a fixed time interval. I am thinking of:
1) using these position,
2) insert them to an array of VertexPositionColor[],
3) and draw them using GraphicsDevice.DrawUserPrimitives() method
but I have no luck so far, the VertexPositionColor is static array, while the amount of position data is always increasing.
I am thinking of using List, but the GraphicsDevice.DrawUserPrimitives() method refuse to take that as an input
protected override void Draw(GameTime gameTime)
{
trail_vertice = new VertexPositionColor;
trail_vertice.Position = Position;
trail_vertice.Color = Color.Black;
trail_amount += 1;
trailList.Add(trail_vertice);
basicEffect.CurrentTechnique.Passes[0].Apply();
graphics.GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.LineStrip, trailList, 0, trail_amount);
}
I do not need advanced effects like using particle engine. Just a single line is enough. Any suggestion?
The C# List<> class has a handy .ToArray() function on it that you can call each time you want to draw the primitives. Hope that helps!
graphics.GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.LineStrip, trailList.ToArray(), 0, trail_amount);
Instead of transforming the list to an array every frame, which seems to me very inefficient, you can calculate the estimated number of vertices you will need to display the trail, create an array of that size and fill it with more values each frame. (One of the argument you pass to DrawUserPrimitives is the number of primitives to draw from the array)
If you can't calculate this, you can also try setting a max length the trail can reach, so that when it reaches that length, it starts overriding the old values. This shouldn't matter much if the camera follows the ball around. If none of these solutions fit your needs, go ahead and use the ToArray function.
Related
I trying to make a game where player only move forward in an infinity map, and the path (just thing of them like points, the path is only the visual) is procedurally generated. I want those path to have different length (something like the tree of life, but only branches of the selected path are generated).
This is how I generate branches without overlap:
List<Vector3> everyPos; //predetermined position
public void Spawn(int amount)
{
List<Vector3> possiblePos = new List<Vector3>(everyPos);
for (int i = 0; i < amount; i++)
{
int index = Random(0, possiblePos.Count); //Find a random position
SpawnObjectAt(currentPosition+possiblePos[index]));//Create a point there
possiblePos.RemoveAt(index); //Remove that position from the list
}
}
The problem is , look at this image(I can't embed image yet):
Red is where player start, green is possible spawn position in the first move.
If there are 2 point spawned at 1 and 2, player choose point1, then the possible position in the second time will be a point in the black zone, which include point2, so if I keep continue there will eventually overlap.
How can I avoid this? I'm making a mobile game so I don't want to cache every single point. Any help would be really appreciated! Thanks!
This is a small web game that have somewhat similar mechanic to what I trying to achieve: newgrounds.com/portal/view/592325/
This is an attempt here to answer, but honestly, you need to provide more information.
Depending on the language you are writing in, you can handle this differently. You may need dynamic allocation, but for now lets assume, since your idea is quite small, that you can just do one large array predefined before compile time.
I assume you know how to make an array, so create one with say, 500 length to start. If you want to 'generate' a link like they did in that game, you simply need a random function, (there is a built in library in pretty much every language I think) and you need to do a little math.
Whatever language you use will surely have a built in graphics library, or you can use a popular easy to use one. I'll just draw a picture to make this clear.
There are a number of ways you can do this mathematically as shown in the image, using angles for example, the simplest way, however, is just to follow the boxes.
If you have worked with graphics before, you know what a vector is, if not, you will need to learn. The 9 vectors presented in this image (0,1) (1,0) (1,1) etc. can be created as vector objects, or even stored as individual ints.
To make your nodes 'move' into another path, you can simply do a rand 1-9 and then correlated the result to one of 9 possible vectors, and then add them to your position vector. It is easiest to do this in array and just use the rand int as the index. In most c derived languages you do that like this:
positionVector += changeVectorArray[rand(1,9)];
You then increment your position vector by one of the 9 vectors as shown above.
The simplest way of making the 'path' is to copy the position before you add the change vector, and then store all of the changes sequentially in another 'path' array.
To show the path on screen, simply draw a line between the first and second, second and third, third and forth elements of your path array. This formula (of joining lines) is discrete mathematics if I'm not mistaken, and you can do much more complicated path shapes if you want, but you get the gist.
That should at least start you off. Without more info I can't really help you.
I could go off on a tangent describe a bunch of different ways you can make this happen differently but its probably easier if you just ask for specifics.
EDIT>>>
Continuing with this answer, yes, looking at it now, the nodes can definitely overlap. To solve this problem you could use collision detection, every time you generate a new 'position', before adding it and drawing the line you have to loop through your array like this:
boolean copy = true;
for(int i = 0; i < getLength(pathArray); i++){
if( newVector == pathArray[i]){
copy=false;
}
}
Then of course, if copy still is true, copy the new position int the pathArray. NOTE: this whole solution is sloppy as hell, and as your array gets larger, your program is going to take longer and longer to search through that loop. This may not also guarantee that the path goes in one direction, but it is likely. And note that the lines will still be able to overlap each other, even though the position vectors can't be on top of one another.
All this considered, I think it will work, the optimization is up to you. I would suggest that there is probably a much more efficient solution using a discrete formula. You can also use such a formula to make the path go in particular directions and do other more complicated things.
You could also quite easily apply constraints on your random rolls if you want to make the path go in a particular direction. But there are so many ways of doing this I can't begin to explain. You could google path-finding algorithms for that.
Good luck.
I am to make a mobile painting game in Unity and I've encountered a serious problem: the Input class in Unity is frame-dependent. Thus I can't get the position of touch frequent enough to make my application draw smoothly; as a result I get something like just points on the background, not connected between each other.
I tried to just connect the points that are detected in Unity, and than my result was just the same points connected with lines, of course. I was trying this in Unity Editor with about 180-200 fps, and on mobile phone with 30-50 fps it looks even worse. I expect that I have to get the touch positions somehow in android studio or Xcode, and only then use them in my C# code in Unity editor.
Am I thinking right to use extern from Unity tools, or there is another easier way to do it directly in Unity? If there is none and I am right, can somebody give me some links to guides/tutorials how to do it and integrate it with Unity? I have never worked outside of Unity and have no experience in integration some external tools with it.
Note: I've tried FixedUpdate without any luck - it doesn't matter how often I try to get the position variables, it is about how often they are updated; I also tried Event.current.mousePosition(in unity editor) in OnGUI method, but it also gave me no difference.
Upd: As I have already said, I need to get positions more frequently than the Input class gives me. It updates not fast enough! Here's what I get without connecting the points. The image shows the mousePosition detection frequency in 180-200 fps. On phones it is even slower!
Upd: Here is my simplified code.
void Draw() //this method is invoked every frame
{
//some calculations of x and y based on Input variables
currentMousePosition = new Vector2( x, y); //current mouse position on sprite
if(currentMousePosition != previousMousePosition)
{
while(currentMousePosition != previousMousePosition)
{
mySprite.texture.SetPixels((int)previousMousePosition.x, (int)previousMousePosition.y, 3,3, myColorArray);
if (currentFrameMousePos.x > previousFrameMousePos.x)
previousFrameMousePos.x++;
if (currentFrameMousePos.x < previousFrameMousePos.x)
previousFrameMousePos.x--;
if (currentFrameMousePos.y > previousFrameMousePos.y)
previousFrameMousePos.y++;
if (currentFrameMousePos.y < previousFrameMousePos.y)
previousFrameMousePos.y--;
}
} else mySprite.texture.SetPixels((int)currentMousePosition.x, (int)currentMousePosition.y, 3,3, myColorArray);
previousMousePosition = currentMousePosition;
}
//mySprite.texture.Apply() is invoked independently in another place to improve performance
The issue is, it is not possible to queue up touch positions that occurred mid frame so by "Quickly" sliding your finger you will miss certain texels on your image. You should look at this line formula Bresenham's line algorithm. This is super fast, and all integer math. Inside your Update() function call this method.
Vector2 oldPoint;
public void UpdateDrawPoint(Vector2 newPoint){
BresenhamLine(newPoint, oldPoint);
oldPoint = newPoint;
}
How do I draw a circle sector (as in a slice of pizza shape) in xna?
I'd like to use one as a timer indicator, so would like to be able change its angle dynamically.
In an ideal world I'm looking for something like this:
Drawsector (float startAngle, float endAngle, ... )
Does such a thing exist?
And if it does - how would I go about drawing a more graphically involved one (as opposed to just block colour)
No. XNA only provides an API for drawing primitive elements called surprisingly primitives.
All is not lost because drawing a circle can be viewed as simply drawing a series of very short interconnected line segments, small enough that you can't tell they are lines, but not too small so as to be inefficient.
In XNA you would draw a PrimitiveType.LineStrip.
MSDN:
The data is ordered as a sequence of line segments; each line segment is described by one new vertex and the last vertex from the previous line seqment. The count may be any positive integer.
e.g. (from MSDN)
GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionColor>(
PrimitiveType.LineStrip,
primitiveList,
0, // vertex buffer offset to add to each element of the index buffer
8, // number of vertices to draw
lineStripIndices,
0, // first index element to read
7 // number of primitives to draw
);
You would need to create your own function to determine the vertices that match the arc you want to draw. You should save that into a permanent index and vertice buffer rather than performing a DrawSector() all the time in your game loop.
Tell me more
Drawing 3D Primitives using Lists or Strips
I am writing a camera module to my XNA project and I encountered a problem lately.
I allowed camera rotation to my module and I got a fabulous bug - every time I draw multiple sprites in the same position, spriteBatch once draws one in front, second time the second one in front, and what is even funnier, sometimes two sprites are shown, with different alphas.
I've made few experiments:
When I set SpriteBatch mode to Deffered it is all ok - but I want to have access to z-index.
When I draw a whole 500x500 tiles array (all the sprites loaded), it is all ok, but when I get like 50x50 square from the array (containing the whole desired screen content) it gets bugged.
Finally different states are always happening for the same angle.
I must add that I do translation myself - in order to get double precision. Here is the method for translations:
public void DrawSprite(Sprite toDraw)
{
// TODO: Think about converting constructor
Vector2D drawingPostion;
Vector2 drawingPos;
drawingPostion = toDraw.Position - Position;
drawingPos.X = (float) drawingPostion.X * GraphicsManager.Instance.UnitToPixels;
drawingPos.Y = (float) drawingPostion.Y * GraphicsManager.Instance.UnitToPixels;
spriteBatch.Draw(toDraw.Texture, drawingPos, toDraw.Source, toDraw.Color,
toDraw.Rotation, toDraw.Origin, toDraw.Scale, toDraw.Effects, toDraw.LayerDepth);
}
My ideas for the problem:
Fix the bug somehow (if it's possible)
Force XNA to sort first by z-index and then by drawing order.
Apply some z-indexes everywhere, where overlapping can occur (don't like this)
Abandon z-index (don't want that either)
As lukegravitt suggested, you should use SpriteSortMode.FrontToBack:
Sprites are sorted by depth in front-to-back order prior to drawing.
This procedure is recommended when drawing opaque sprites of varying
depths.
Reference MSDN.
So you can easily set the z-index with the last parameter of SpriteBatch.Draw:
float layerDepth
The depth of a layer. By default, 0 represents the front layer and 1
represents a back layer. Use SpriteSortMode if you want sprites to be
sorted during drawing.
Reference MSDN.
I've finally picked the option C), here is how it works in my code:
public void DrawSprite(Sprite toDraw)
{
// TODO: Think about converting constructor
Vector2D drawingPostion;
Vector2 drawingPos;
drawingPostion = toDraw.Position - Position;
drawingPos.X = (float) drawingPostion.X * GraphicsManager.Instance.UnitToPixels;
drawingPos.Y = (float) drawingPostion.Y * GraphicsManager.Instance.UnitToPixels;
// proceeding to new z-index
zsortingValue += 0.000001f;
spriteBatch.Draw(toDraw.Texture, drawingPos, toDraw.Source, toDraw.Color,
toDraw.Rotation, toDraw.Origin, toDraw.Scale, toDraw.Effects, toDraw.LayerDepth + zsortingValue);
}
where zsortingValue is zeroed whenever a frame begins. This way each sprite can have its own sorting value, which is being enhanced only.
Until recently, our game checked collisions by getting the colour data from a section of the background texture of the scene. This worked very well, but as the design changed, we needed to check against multiple textures and it was decided to render these all to a single RenderTarget2D and check collisions on that.
public bool TouchingBlackPixel(GameObject p)
{
/*
Calculate rectangle under the player...
SourceX,SourceY: Position of top left corner of rectangle
SizeX,SizeY: Aproximated (cast to int from float) size of box
*/
Rectangle sourceRectangle = new Rectangle(sourceX, sourceY,
(int)sizeX, (int)sizeY);
Color[] retrievedColor = new Color[(int)(sizeX * sizeY)];
p.tileCurrentlyOn.collisionLayer.GetData(0, sourceRectangle, retrievedColor,
0, retrievedColor.Count());
/*
Check collisions
*/
}
The problem that we've been having is that, since moving to the render target, we are experiencing massive reductions in FPS.
From what we've read, it seems as if the issue is that in order to get data from the RenderTarget2D, you need to transfer data from the GPU to the CPU and that this is slow. This is compounded by us needing to run the same function twice (once for each player) and not being able to keep the same data (they may not be on the same tile).
We've tried moving the GetData calls to the tile's Draw function and storing the data in a member array, but this does not seem to have solved the problem (As we are still calling GetData on a tile quite regularly - down from twice every update to once every draw).
Any help which you could give us would be great as the power that this collision system affords us is quite fantastic, but the overhead which render targets have introduced will make it impossible to keep.
The simple answer is: Don't do that.
It sounds like offloading the compositing of your collision data to the GPU was a performance optimisation that didn't work - so the correct course of action would be to revert the change.
You should simply do your collision checks all on the CPU. And I would further suggest that it is probably faster to run your collision algorithm multiple times and determine a collision response by combining the results, rather than compositing the whole scene onto a single layer and running collision detection once.
This is particularly the case if you are using the render target to support transformations before doing collision.
(For simple 2D pixel collision detection, see this sample. If you need support for transformations, see this sample as well.)
I suppose, your tile's collision layer does not change. Or at least changes not very frequently. So you can store the colors for each tile in an array or other structure. This would decrease the amount of data that is transfered from the GPU to CPU, but requires that the additional data stored in the RAM is not too big.