I´m making my first game in Game Maker.
In the game i need to the user to draw a figure, for example a rectangle, and the game has to recognize the figure. How can i do this?
Thanks!
Well, that is a pretty complex task. To simplify it, you could ask him to place a succession of points, using the mouse coordinates in the click event, and automatically connect them with lines. If you store every point in the same ds_list structure, you will be able to check conditions of angle, distance, etc. This way, you can determine the shape. May I ask why you want to do this ?
The way I would solve this problem is pretty simple. I would create a few variables for each point when someone clicked on one of the points it would equal true. and wait for the player to click on the next point. If the player clicked on the next point i would call in a sprite as a line using image_angle to line both points up and wait for the player to click the next point.
Next I would have a step event waiting to see if all points were clicked and when they were then to either draw a triangle at those coordinates or place an sprite at the correct coordinates to fill in the triangle.
Another way you could do it would be to decide what those points would be and check against mouse_x, and mouse_y to see if that was a point and if it was then do as above. There are many ways to solve this problem. Just keep trying you will find one that works for your skill level and what you want to do.
You need to use draw_rectangle(x1, y1, x2, y2, outline) function. As for recognition of the figure, use point_in_rectangle(px, py, x1, y1, x2, y2).
I'm just wondering around with ideas cause i can't code right now. But listen to this, i think this could work.
We suppose that the user must keep his finger on touchscreen or an event is triggered and all data from the touch event is cleaned.
I assume that in future you could need to recognize other simple geometrical figures too.
1 : Set a fixed amount of pixels of movement defined dependent on the viewport dimension (i'll call this constant MOV from now on), for every MOV you store in a buffer (pointsBuf) the coordinates of the point where the finger is.
2 : Everytime a point is stored you calculate the average of either X and Y coordinates for every point. (Hold the previous average and a counter to reduce time complexity). Comparing them we now can know the direction and versus of the line. Store them in a 2D buffer (dirVerBuf).
3 : If a point is "drastically" different from the most plain average between the X and Y coordinates we can assume that the finger changed direction. This is where the test part of MOV comes critical, we must assure to calculate an angle now. Since only a Parkinsoned user would make really distorted lines we can assume at 95% that we're safe to take the 2nd point that didn't changed the average of the coordinate as vertex and let's say the last and the 2nd point before vertex to calculate the angle. You have now one angle. Test the best error margin of the user to find if the angle is about to be a 90, 60, 45, ecc.. degrees angle. Store in a new buffer (angBuf)
4 : Delete the values from pointsBuf and repeat step 2 and 3 until the user's finger leaves the screen.
5 : if four of the angles are of 90 degrees, the 4 versus and two of the directions are different, the last point is somewhat near (depending from MOV) the first angle stored and the two X lines and the Y lines are somewhat equal, but of different length between them, then you can connect the 4 angles using the four best values next to the 4 coordinates to make perfect rectangular shape.
It's late and i could have forgotten something, but with this method i think you could even figure out a triangle, a circle, ecc..
With just some edit and confronting.
EDIT: If you are really lazy you could instead use a much more space complexity heavy strategy. Just create a grid of rectangles or even triangles of a fixed dimension and check which one the finger has touched, connect their centers after you'have figured out the shape, obviously ignoring the "touched for mistake" ones. This would be extremely easy to draw even circles using the native functions. Gg.
Related
Currently I have a program that allows the user to paint on it by capturing the mouse position every 0.05 seconds and drawing a line between a point and the next. With that setup I am looking for a way to identify shapes like a circle, a rectangle or the letter 'P'.
My current algorithm divides the screen on sections, then marks the sections with points recorded by the player and makes a matrix with the marked sections, then compares that matrix with every shape matrix.
This lacks any kind of support for rotations, sizes or positions. Also the control of the threshold is tricky returning in most cases fake results.
I need an algorithm that allows to identify for example a ' P ' as a ' P '.
Note: My current application is running on a c++ framework so any libraries or tools are welcome but I am interested on the algorithm behind.
Edit: After thinking around the problem I have changed the current grid on the screen, instead of that I capture the points and shift them to resize
the shape so it fits on a grid and over that grid compare with the known shapes.
Picture of the process
This solves the position and size problems while being fast enough, also rotating the input and then resizing in a loop may solve the rotation problem (seems though it would have an high cost and won't be very reliable)
I would gladly welcome alternative methods of handling shape comparison or the rotation.
After thinking around the problem I have changed the current grid on the screen, instead of that I capture the points and shift them to resize
the shape so it fits on a grid and over that grid compare with the known shapes.
Picture of the process
This solves the position and size problems while being fast enough, also rotating the input and then resizing in a loop may solve the rotation problem (seems though it would have an high cost and won't be very reliable)
So I have an arrayList of the locations of each pixel (represent resources in my game). arrayList.get(0); would get me the top right point, and then continuing by increment the x coordinate. When it reaches the end, it increments the y coordinate and repeats until it gets to the last point (left-most, bottom)/end of the list.
I want to build a factory site, but first I need to pick an intelligent location to build my factory/resource site. See picture (red is an ideal location).
If I simply take an average of all points, it would give me somewhere around orange arrow (I'm guessing).
Sounds like you're looking for the highest point density. This StackOverflow answer discusses a couple of algorithms, the first doing box convolution.
Of course if each pixel just has value 1 this may be more than you need.
I'm developing an AI sandbox and I would like to calculate what every living entity can see.
The rule is to simply hide what's behind the edges of the shapes from the point of view of the entity. The image clarifies everything:
alt text http://img231.imageshack.us/img231/2972/shadows.png
I need it either as an input to the artificial intelligence either graphically, to show it for a specific entity while it moves..
Any cool ideas?
This isn't the fastest algorithm but it produces a polygon which might be useful for further analysis by your AI:
For each line segment, calculate the angle between the entity and the two endpoints.
Sort the points by angle.
“Sweep” around 360°, keeping track of which line segments intersect with the sweep line. When you cross the beginning-of-segment point, you add that segment to the set; when you cross the end-of-segment point, you remove that segment from the set.
The closest line segments form a polygon of what's visible. The polygon is the union of triangle slivers.
I realize this explanation isn't great, but I have an online demo here that you can play with to get a sense for how it works. Extending it to work with circles probably isn't too bad (famous last words).
If you're using simple shapes to block the entity's view, there is an easy way to do this that I have implemented:
Create a VisionWave object which can move either horizontally or vertically. You can define a VisionWave using a source coordinate, two lines that intersect that point, and a distance from the source point.
You should have 4 waves: one going up, one down, one left, and one right, and the lines that define them should have a slope of 1 and -1 (i.e., an X). My crude drawing below shows one wave (going right) as represented by the > character.
\ /
\ />
\ / >
# >
/ \ >
/ \>
/ \
Make a loop that propagates each wave one pixel at a time. When you propagate the wave, you want to do the following:
Mark every pixel that the wave is touching as visible.
If any of the pixels that the wave touches block light, then you want to split the wave into two, and recursively propagate each one.
I implemented a system like this in my Roguelike and it is very fast. Make sure to profile your code for bottlenecks.
If you're very clever you might try circular waves instead of straight lines, but I don't know if it would be faster due to the trigonometric calculations.
Determine which vertices are visible to your eye point, then project those vertices back away from the eye point on a straight line to make new vertices. Close the shape and you will have created a polygon representing the invisible area.
See shadow volumes for the 3D equivalent.
Greetings,
I'm working on a game project that uses a 3D variant of hexagonal tile maps. Tiles are actually cubes, not hexes, but are laid out just like hexes (because a square can be turned to a cube to extrapolate from 2D to 3D, but there is no 3D version of a hex). Rather than a verbose description, here goes an example of a 4x4x4 map:
(I have highlighted an arbitrary tile (green) and its adjacent tiles (yellow) to help describe how the whole thing is supposed to work; but the adjacency functions are not the issue, that's already solved.)
I have a struct type to represent tiles, and maps are represented as a 3D array of tiles (wrapped in a Map class to add some utility methods, but that's not very relevant).
Each tile is supposed to represent a perfectly cubic space, and they are all exactly the same size. Also, the offset between adjacent "rows" is exactly half the size of a tile.
That's enough context; my question is:
Given the coordinates of two points A and B, how can I generate a list of the tiles (or, rather, their coordinates) that a straight line between A and B would cross?
That would later be used for a variety of purposes, such as determining Line-of-sight, charge path legality, and so on.
BTW, this may be useful: my maps use the (0,0,0) as a reference position. The 'jagging' of the map can be defined as offsetting each tile ((y+z) mod 2) * tileSize/2.0 to the right from the position it'd have on a "sane" cartesian system. For the non-jagged rows, that yields 0; for rows where (y+z) mod 2 is 1, it yields 0.5 tiles.
I'm working on C#4 targeting the .Net Framework 4.0; but I don't really need specific code, just the algorithm to solve the weird geometric/mathematical problem. I have been trying for several days to solve this at no avail; and trying to draw the whole thing on paper to "visualize" it didn't help either :( .
Thanks in advance for any answer
Until one of the clever SOers turns up, here's my dumb solution. I'll explain it in 2D 'cos that makes it easier to explain, but it will generalise to 3D easily enough. I think any attempt to try to work this entirely in cell index space is doomed to failure (though I'll admit it's just what I think and I look forward to being proved wrong).
So you need to define a function to map from cartesian coordinates to cell indices. This is straightforward, if a little tricky. First, decide whether point(0,0) is the bottom left corner of cell(0,0) or the centre, or some other point. Since it makes the explanations easier, I'll go with bottom-left corner. Observe that any point(x,floor(y)==0) maps to cell(floor(x),0). Indeed, any point(x,even(floor(y))) maps to cell(floor(x),floor(y)).
Here, I invent the boolean function even which returns True if its argument is an even integer. I'll use odd next: any point point(x,odd(floor(y)) maps to cell(floor(x-0.5),floor(y)).
Now you have the basics of the recipe for determining lines-of-sight.
You will also need a function to map from cell(m,n) back to a point in cartesian space. That should be straightforward once you have decided where the origin lies.
Now, unless I've misplaced some brackets, I think you are on your way. You'll need to:
decide where in cell(0,0) you position point(0,0); and adjust the function accordingly;
decide where points along the cell boundaries fall; and
generalise this into 3 dimensions.
Depending on the size of the playing field you could store the cartesian coordinates of the cell boundaries in a lookup table (or other data structure), which would probably speed things up.
Perhaps you can avoid all the complex math if you look at your problem in another way:
I see that you only shift your blocks (alternating) along the first axis by half the blocksize. If you split up your blocks along this axis the above example will become (with shifts) an (9x4x4) simple cartesian coordinate system with regular stacked blocks. Now doing the raytracing becomes much more simple and less error prone.
I have a problem with circle-circle collision detection.I used the following algorithm
func collision(id,other.id)
{
var vaP1,vaP2,dis,va1,vb1,va2,vb2,vp1,vp2,dx,dy,dt;
if (id!=other.id)
{
dx=other.x-x;
dy=other.y-y;
dis=sqrt(sqr(dx)+sqr(dy));
if dis<=radius+other.radius
{
//normalize
dx/=dis;
dy/=dis;
//calculate the component of velocity in the direction
vp1=hspeed*dx+vspeed*dy;
vp2=other.hspeed*dx+other.vspeed*dy;
if (vp1-vp2)!=0
{
dt=(radius+other.radius-dis)/(vp1-vp2);
//move the balls back so they just touch
x-=hspeed*dt;
y-=vspeed*dt;
other.x-=other.hspeed*dt;
other.y-=other.vspeed*dt;
//projection of the velocities in these axes
va1=(hspeed*dx+vspeed*dy);
vb1=(vspeed*dx-hspeed*dy);
va2=(other.hspeed*dx+other.vspeed*dy);
vb2=(other.vspeed*dx-other.hspeed*dy);
//new velocities in these axes. take into account the mass of each ball.
vaP1=(va1+bounce*(va2-va1))/(1+mass/other.mass);
vaP2=(va2+other.bounce*(va1-va2))/(1+other.mass/mass);
hspeed=vaP1*dx-vb1*dy;
vspeed=vaP1*dy+vb1*dx;
other.hspeed=vaP2*dx-vb2*dy;
other.vspeed=vaP2*dy+vb2*dx;
//we moved the balls back in time, so we need to move them forward
x+=hspeed*dt;
y+=vspeed*dt;
other.x+=other.hspeed*dt;
other.y+=other.vspeed*dt;
}
}
}
x=ball 1 x-position
y=ball 1 y-position
other.x= ball 2 x position
other.y=ball 2 y position
this algorithm works well when i have a ball image of 40 x 40 pixel and ball center is (20,20) means image consists only ball.But the problem arises when image size is 80 x 80.and ball center position is (60,60),means ball is lower right corner with radius 20.
in this case there are multiple collision occur,means the portion
x+=hspeed*dt;
y+=vspeed*dt;
other.x+=other.hspeed*dt;
other.y+=other.vspeed*dt;
unable to seperate the ball /velocity does not change according to collision.
I have changed the value of x which is the center of image 40,40 to 60,60 center of ball adding 20.but the result is same .Can any one tell me what is the problem.I think algorithm is correct because it works nicely in all other case and lots of people used this algorithm.problem is changing position from image center to ball center.what correction should i do for this??? or any idea.if someone want to help plz give me e-mail address so that i can send my full project.
I didnt have the mental power to digest your entire question, but here is my 2 cents on how to solve your problem
1) The simplest way to detect a circle collision with another is to check if their distance is less than the radius of the combined circles. (i might be wrong with the math, so correct me if i am wrong)
Circle c1,c2;
float distance = DISTANCE(c1.center,c2.center);
if(distance < c1.radius + c2.radius)
{
// collision .. BOOOOOOM
}
2) Try to use accurate data types. Try not to convert floats to integers without checking overflow, underflow and decimal points. Better still, just use floats .
3) Write a log and trace through your values. See if there are any obvious maths errors .
4) Break down your code to its simplest portion. Try to remove all that velocity computation to get the simplest movements to help you debug.
I will not give you the answer that you are looking for and I am not sure someone else will. The amount of code that must be decyphered to get you the answer may not warrant the reward. What I would recommend is to losen the coupling in your algorithm. The function above is doing way too much work.
Ideally you would have a collision detection that concentrated only on the collision and not on advancing the balls. Something like function shown below and that would allow other developers to help you more easily if you still had a problem.
function(firstCircleCenterX, firstCircleCenterY, secondCircleCenterX, secondCircleCenterY, firstCircleRadius, secondCircleRadius)
{
...this code should concentrate on logic to determine collision
...use pythagoran theory to find distance between the two centers
...if the distance between the two centers is less than ((2*firstCircleRadius)+(2*secondCircleRadius) then you have a collision
...return true or false depending on collision
}