Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I am making a top down, rpg-type game - similar to Pokemon, but I am stuck at character movement. Basically, what I want to achieve is a smooth tile based movement system for my player and other people on the map. Has anyone managed to do this effectively? If so, how?
If you are using a grid system, like Pokémon uses, you might be able to achieve this by setting a speed at which they can move between tiles.
For example, if you made it so that they can move one tile a second, you can then use (float)gameTime.ElapsedGameTime.TotalSeconds in your Update function to determine how quickly the game is updating. From this, you should be able to make it so that the character moves ((float)gameTime.ElapsedGameTime.TotalSeconds * TileSize) each update.
This would mean that if they have 4 updates a second (very slow, but for example), they would move 1/4 of the distance across the tile every update, and reach the end point by the end of the movement time period (1 second in this case). In this situation, if you had 32 pixel tiles, they would move 0.25 * 32 every update, or 8 pixels.
Hope this helps.
The 'technical' word for what you want is probably 'interpolation'.
I think the simplest thing you want to do is interpolate the unit position between its starting point (the middle of starting tile) and its ending point (the middle of ending tile) in the time period you want to give it a smooth movement.
Formula goes something like this:
float k = timeSinceStarted / durationOfMovement;
pos.X = startPos.X + (endPos.X - startPos.X) * k;
pos.Y = startPos.Y + (endPos.Y - startPos.Y) * k;
In a game, it's probably better to pre-compute the delta, and add increments instead of storing start position. Something like this (Note: I haven't double checked this computation).
delta = endPos - startPos;
position += delta * (timeSinceLastUpdate / durationOfMovement);
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
What is the most efficient way to find the quadrant of an angle given in Objective-C (assuming that the boundary angles 0, 90, 270, 360 etc. all fall within a quadrant) ?
You don't need any magic functions.
Full circle contains 2*Pi radians and 4 quadrants.
So just divide angle by Pi/2 and make floor rounding to get 0..3 quadrant numbering (add 1 if 1..4 is needed)
Python example. Note that integer modulo operation % 4 provides "angle normalisation" so function works with large and negative angles
(Swift % does not work similar according to table here, so you might need to make something like return ((floor(2.0 * angle / math.pi) % 4 + 4) %4)
import math
def quadrant(angle):
return math.floor(2.0 * angle / math.pi) % 4
print(quadrant(math.pi/4))
print(quadrant(math.pi/4 + math.pi))
print(quadrant(math.pi/4 - math.pi))
0
2
2
I have some experience with Metal and quite a bit with Unity and am familiar with setting up meshes, buffers, and the backing data for drawing; but not so much the math/shader side. What I'm struggling with is how to get an endless scrolling world. So if I pan far to the right side I can see the left side and keep going.
The application of this would be a seamless terrain that a player could scroll in any direction forever and have it just wrap.
I don't want to duplicate everything on draw and offset it, that seems horrendously inefficient. I am hoping for a way to either use some magic matrix math or some sort of shader to get things wrapping/drawing where they should when panning the map. I've searched all over for some sort of guide or explanation of how to get this working but haven't come up with anything.
I know a lot of old (dos) games did this somehow, is it still possible? Is there a reason why it seems the industry has migrated away from this type of scrolling (bounding to edges vs wrapping)?
I have created a simple example demonstrating what you're looking for (I think).
The basic idea of it is that you draw the map in a repeating grid, using the drawPrimitives(type:vertexStart:vertexCount:instanceCount:) method on MTLRenderCommandEncoder. As the instance count you want to pass in the number of identical maps you want to draw, extending it as far as needed to not see where it ends. In my example I used a simple 5x5 grid.
To not have the user see the edge of the map, we're gonna calculate their position modulo 1 (or whatever size your map is):
func didDrag(dx: CGFloat, dy: CGFloat) {
// Move user position on drag, adding 1 to not get below 0
x += Float(dx) * draggingSpeed + 1
z += Float(dy) * draggingSpeed + 1
x.formTruncatingRemainder(dividingBy: 1)
z.formTruncatingRemainder(dividingBy: 1)
}
This is how it looks:
Just a follow up on what I have actually implemented. First I essentially have an array of x,y points with altitude, terrain type and all that jazz. Using some simple % and additions/subtractions it is trivial to get the nodes around a point to generate triangles
On a draw I calculate the first showing point and the last showing point and calculate the groups of triangles shown between those points. The first/last point take into account wrapping, it is then pretty trivial to have an endless wrapping world. For each group a translation offset is passed via a uniform matrix for that group which will position that section where it should belong.
I set it via renderEncoder.setVertexBytes(&uniform, length:..., offset:...)
The problem is simple: I want to move (and later, be able to rotate) an image. For example, every time i press the right arrow on my keyboard, i want the image to move 0.12 pixels to the right, and every time i press the left arrow key, i want the image to move 0.12 pixels to the left.
Now, I have multiple solutions for this:
1) simply add the incremental value, i.e.:
image.x += 0.12;
this is of course assuming that we're going to the right.
2) i multiplicate the value of a single increment by the times i already went into this particular direction + 1, like this:
var result:Number = 0.12 * (numberOfTimesWentRight+1);
image.x = result;
Both of these approaches work but produce similiar, yet subtly different, results. If we add some kind of button component that simply resets the x and y coordinates of the image, you will see that with the first approach the numbers don't add up correctly.
it goes from .12, .24, .359999, .475 etc.
But with the second approach it works well. (It's pretty obvious as to why though, it seems like += operations with Numbers are not really precise).
Why not use the second approach then? Well, i want to rotate the image as well. This will work for the first attempt, but after that the image will jump around. Why? In the second approach we never took the original position of the image in account. So if the origin-point shifts a bit down or up because you rotated your image, and THEN you try to move the image again: it will move to the same position as if you hadn't rotated before.
Alright, to make this short:
How can i reliably move, scale and rotate images for 1/10 of a pixel?
Short answer: I don't know! You're fighting with floating point math!
Luckily, I have a workaround, if you don't mind.
You store the location (x and y) of the image in a separate variable... at a larger scale. Such as 100x. So 123.45 becomes 12345, and you then divide by 100 to set the attribute that flash uses to display.
Yes, there are limits to number sizes too, but if you're willing to accept some error rate, and the fact that you'll be limited to, I dunno, a million pixels in each direction, you can fit it in a regular int. The only rounding error you will encounter will be a single rounding error when you divide by 100 (or the factor you used). So instead of the compound rounding error which you described (0.12 * 4 = 0.475), you should see things like 0.47999999. Which doesn't matter because it's, well, so small.
To expand on #Pimgd answer a bit, you're probably hitting a floating point error (multiple +='s will exaggerate the error more than one *='s) - Numbers in Flash are 53-bit precision.
There's also another thing to keep in mind, which is probably playing a bigger role with such small movement values; Flash positions all objects using twips, which is roughly about 1/20th of a pixel, or 0.05, so all values are rounded to this. When you say image.x += 0.12, it's actually the equivalent of image.x += 0.10, hence which the different becomes apparent; you're losing 0.02 of a pixel with every move.
You should be able to get around it by moving to another scale, as #Pimgd says, or just storing your position separately - i.e. work from a property _x rather than image.x so you're not losing that precision everytime:
this._x += 0.12;
image.x = this._x;
How to make a 2d world with fixed size, which would repeat itself when reached any side of the map?
When you reach a side of a map you see the opposite side of the map which merged togeather with this one. The idea is that if you didn't have a minimap you would not even notice the transition of map repeating itself.
I have a few ideas how to make it:
1) Keeping total of 3x3 world like these all the time which are exactly the same and updated the same way, just the players exists in only one of them.
2) Another way would be to seperate the map into smaller peaces and add them to required place when asked.
Either way it can be complicated to complete it. I remember that more thatn 10 years ago i played some game like that with soldiers following each other in a repeating wold shooting other AI soldiers.
Mostly waned to hear your thoughts about the idea and how it could be achieved. I'm coding in XNA(C#).
Another alternative is to generate noise using libnoise libraries. The beauty of this is that you can generate noise over a theoretical infinite amount of space.
Take a look at the following:
http://libnoise.sourceforge.net/tutorials/tutorial3.html#tile
There is also an XNA port of the above at: http://bigblackblock.com/tools/libnoisexna
If you end up using the XNA port, you can do something like this:
Perlin perlin = new Perlin();
perlin.Frequency = 0.5f; //height
perlin.Lacunarity = 2f; //frequency increase between octaves
perlin.OctaveCount = 5; //Number of passes
perlin.Persistence = 0.45f; //
perlin.Quality = QualityMode.High;
perlin.Seed = 8;
//Create our 2d map
Noise2D _map = new Noise2D(CHUNKSIZE_WIDTH, CHUNKSIZE_HEIGHT, perlin);
//Get a section
_map.GeneratePlanar(left, right, top, down);
GeneratePlanar is the function to call to get the sections in each direction that will connect seamlessly with the rest of your world.
If the game is tile based I think what you should do is:
Keep only one array for the game area.
Determine the visible area using modulo arithmetics over the size of the game area mod w and h where these are the width and height of the table.
E.g. if the table is 80x100 (0,0) top left coordinates with a width of 80 and height of 100 and the rect of the viewport is at (70,90) with a width of 40 and height of 20 you index with [70-79][0-29] for the x coordinate and [90-99][0-9] for the y. This can be achieved by calculating the index with the following formula:
idx = (n+i)%80 (or%100) where n is the top coordinate(x or y) for the rect and i is in the range for the width/height of the viewport.
This assumes that one step of movement moves the camera with non fractional coordinates.
So this is your second alternative in a little bit more detailed way. If you only want to repeat the terrain, you should separate the contents of the tile. In this case the contents will most likely be generated on the fly since you don't store them.
Hope this helped.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I have a canvas which contains a single myComponentA. A myComponentA contains a MyComponentB. The myComponentB contains a number of myComponentA's giving a tree structure...Ok so far.
The structure is stored as an XML file.
When I load a big (60 or so components), the components are not visible... When I change the player quality to low or medium they appear...!?
Towards the bottom of the diagram a component is clipped through the middle as though it has been cut off...(The containing canvas continues on empty...)
This is probably an issue with the flex measuring mechanism. Your myComponentA should probably report its measuredHeight and measuredWidth to the parent container. This will likely be done, in your case, in an override of the measure function. e.g,
override protected function measure():void {
measuredWidth = //x position + width of rightmost child
measuredHeight = //y position + height of bottommost child
super.measure();
}
If you do something like this in both myComponentA and myComponentB, and you inherit from a Container (e.g., canvas) then things should work mostly. If your components inherit from UIComponent, you might have more trouble (i.e., there won't be any scrollbars).
Keep in mind that the measure function only sets the measuredHeight and measuredWidth. Depending on your situation, you may need to overide updateDisplayList as well to properly set the actual height/width/positions of the children.