Having trouble with wall collisions - collision

I'm working on this game right now (with GameMaker Studio 2) and I'm currently coding walls and when I tried making horizontal collision, it worked fine, but when I made floor collision I would get stuck in the walls and floor
here's the code:
//input
keyRight = keyboard_check(ord("D"));
keyLeft = keyboard_check(ord("A"));
keyUp = keyboard_check(ord("W"));
keyDown = keyboard_check(ord("S"));
// direction
var move2 = (keyDown - keyUp) * vspd;
var move = (keyRight - keyLeft) * hspd;
//collision stuff idk
if place_meeting ( x + move, y ,obj_wall)
move2= 0;
if place_meeting ( x + move2, y ,obj_wall)
move= 0;
// comiit
x += move
y += move2
If someone could tell me what I'm doing wrong and how to do it right please tell me I would appreciate it thanks in advance.

You are checking for a wall at a horizontal offset in both cases and also move/move2 assignments are mixed up. So, instead of
if place_meeting ( x + move, y ,obj_wall)
move2= 0;
if place_meeting ( x + move2, y ,obj_wall)
move= 0;
you could have
if place_meeting ( x + move, y ,obj_wall)
move= 0;
if place_meeting ( x, y + move2 ,obj_wall)
move2= 0;
Or a small loop if you need the object to approach the collision target.

Related

Hill Climbing Algorithm for finding Maxima in MATALB

I am trying to make a program in MATLAB in which we have to find the maxima.
The algorithm which I am using is compare the given point with two adjacent points.
If the next point is greater than the present , iterate in positive direction.
If the next point is smaller than the present, iterate in the negative direction.
If the previous point and the next point are less than the present, maxima reached.
I have made a while loop with flag variable.But it is not able to detect the maxima.
I intialize x to some number intially (say x = 0)
The function 'f(x) = -x^2 -3;'
The variable 'xint ' is the interval which is set to say 0.1.
The variable 'i' is just to keep a count.
clc
clear all
syms x
f(x) = -x^2+3;
max = 0;
x = 0;
xint = 0.1;
flag =1;
while(flag ==1)
fprintf('\ninside while\n')
if(f(x+xint)> f(x))
x = x + xint;
fprintf('inside first: Value of x is set to = %f, where function value is %f', x, f(x));
elseif(f(x+xint) < f(x))
x = x-xint;
fprintf('inside second: Value of x is set to = %f, where function value is %f', x, f(x));
else if(f(x-xint)<f(x) & f(x+xint) < f(x))
disp('Max detected')
max = x;
flag =0;
end
i = i+1;
end
Any help will be of use to me.
Thank You very much.
Anupam
Input :
f(x) = -x^2 +3;
Output:
The program does not enter into the third else if statement.And thus while loop keeps running.
You can't have a condition for the else clause. Additionally, if you were to make the else into an elseif it was be unreachable as the condition you wrote there can I be true when the condition you have for the previous elseif is true, but in a if-elseif statements only one clause gets executed every time.
Change the condition of the elseif and get to of the condition for the else:
elseif(f(x-xint) > f(x))
x = x-xint;
fprintf('inside second: Value of x is set to = %f, where function value is %f', x, f(x));
else
disp('Max detected')
max = x;
flag =0;
end
I am assuming xint is a positive value and your function is second degree polinomial with negative constant (i.e. y = a*x^2+b where a < 0), then:
if f(x+xint) > f(x) % go to right.
x1 = x+xint;
else % go to left
x1 = x
xint = -xint;
end
while f(x1) > f(x1+xint)
x1 = x1+xint;
end
Here x1 is maxima or something very close to it.

Kaczmarz animation

i am asking for help.. I want to animate the Kaczmarz method on Matlab. It's method allows to find solution of system of equations by the serial projecting solution vector on hyperplanes, which which is given by the eqations of system.
And i want make animation of this vector moving (like the point is going on the projected vectors).
%% System of equations
% 2x + 3y = 4;
% x - y = 2;
% 6x + y = 15;
%%
A = [2 3;1 -1; 6 1];
f = [4; 2; 15];
resh = pinv(A)*f
x = -10:0.1:10;
e1 = (1 - 2*x)/3;
e2 = (x - 2);
e3 = 15 - 6*x;
plot(x,e1)
grid on
%
axis([0 4 -2 2])
hold on
plot(x,e2)
hold on
plot(x,e3)
hold on
precision = 0.001; % точность
iteration = 100; % количество итераций
lambda = 0.75; % лямбда
[m,n] = size(A);
x = zeros(n,1);
%count of norms
for i = 1:m
nrm(i) = norm(A(i,:));
end
for i = 1:1:iteration
j = mod(i-1,m) + 1;
if (nrm(j) <= 0), continue, end;
predx = x;
x = x + ((f(j) - A(j,:)*x)*A(j,:)')/(nrm(j))^2;
p = plot(x);
set(p)
%pause 0.04;
hold on;
if(norm(predx - x) <= precision), break, end
end
I wrote the code for this method, by don't imagine how make the animation, how I can use the set function.
In your code there are a lot of redundant and random pieces. Do not call hold on more than once, it does nothing. Also set(p) does nothing, you want to set some ps properties to something, then you use set.
Also, you are plotting the result, but not the "change". The change is a line between the previous and current, and that is the only reason you'd want to have a variable such as predx, to plot. SO USE IT!
Anyway, this following code plots your algorithm. I added a repeated line to plot in green and then delete, so you can see what the last step does. I also changed the plots in the begging to just plot in red so its more clear what is each of the things.
Change your loop for:
for i = 1:1:iteration
j = mod(i-1,m) + 1;
if (nrm(j) <= 0), continue, end;
predx = x;
x = x + ((f(j) - A(j,:)*x)*A(j,:)')/(nrm(j))^2;
plot([predx(1) x(1)],[predx(2) x(2)],'b'); %plot line
c=plot([predx(1) x(1)],[predx(2) x(2)],'g'); %plot it in green
pause(0.1)
children = get(gca, 'children'); %delete the green line
delete(children(1));
drawnow
% hold on;
if(norm(predx - x) <= precision), break, end
end
This will show:

Game piece movement optimization; given certain rules, find the minimum number of moves

Alright, so this is a fun one. I'm trying to code the movement of a piece in Japanese chess (also called shogi), specifically the silver general. The rules of the piece's movement are as such:
For position (x,y), the piece can move to either (x-1,y+1), (x,y+1), (x+1,y+1), (x-1,y-1), or (x+1,y-1). In other words, the piece can move to any of the spaces directly diagonal to it or to the space directly above it, but cannot move directly left, right, or down.
So I'm defining a function that takes the starting position (sx,sy) and the final position (gx,gy) as arguments and finds the quickest path between the two. Things seem to work for the case in which the starting and ending coordinates lie together on a horizontal or vertical line, but things start to fall apart after that. I don't know if I'm missing a condition, or if there's a better way to do this, but the function needs to work with the given arguments. Does anybody have any advice that might point me in the right direction? My code is as follows:
def minSteps(sx,sy,gx,gy):
count = 0
while [sx,sy] != [gx,gy]:
if (gy != sy and gx == sx):
if gy > sy:
sx = sx
sy += 1
count += 1
else:
sx += 1
sy -= 1
count += 1
elif (gy == sy and gx != sx):
if gx > sx:
sx += 1
sy += 1
count += 1
else:
sx -= 1
sy += 1
count += 1
elif (gy != sy and gx != sx):
if gy > sy:
if gx > sx:
sx += 1
sy += 1
count += 1
else:
sx -= 1
sy += 1
count += 1
if gy < sy:
if gx > sx:
sx += 1
sy -= 1
count += 1
else:
sx -= 1
sy -= 1
count += 1
return count
You might be able to try the A* Search Algorithm which can search the problem space for the minimum number of steps. Given the limited move options, the algorithm may need to be tweaked to specialise for the Shogi-limited movements.
Hope this Helps!
I assume the space is "infinite". So, I'm naming the different moves this way:
A = (x+1,y+1)
B = (x+1,y-1)
C = (x-1,y-1)
D = (x-1,y+1)
E = (x,y+1)
Since the order of these moves doesn't matter, instead of looking for a path, I prefer to count how many As, how many Bs, etc.
If we only consider A, B, C and D moves, then, we would have a grid seen in diagonal.
Points that are not part of this grid can be connected to the grid using an E move.
So, step 1: find x and y relative to the starting point:
x = gx-sx;
y = gy-sy;
Step 2: all counters to zero:
a = 0;
b = 0;
c = 0;
d = 0;
e = 0;
Step 3: if the point is not in "the grid", move it to the grid, using an E move:
if ((x&1) ^ (y&1)) {e=1; y--;}
Step 4: since it is easier for me to operate in positive numbers domain, numbers are mirrored in case of negative:
if (x<0) {hor=1; x=-x;}
else hor=0;
if (y<0) {ver=1; y=-y;}
else ver=0;
Step 5: Once all numbers are positive, I found either B and A counters, or D and A counters:
if (x>y) {b=(x-y)/2; a=y+b;}
else {d=(y-x)/2; a=x+d;}
Step 6: If numbers were mirrored, swap the counters accordingly (right becomes left, up becomes down):
if (hor) {hor=a; a=d; d=hor; c=b; b=0;}
if (ver) {ver=a; a=b; b=ver; ver=c; c=d; d=ver;}
...and that's it. Solution is in a,b,c,d,e counters. If you really need a path, you can derive it from the move counters.
Final note: there are multiple solutions in counters, because you can convert: A + D = 2 E

Supercover DDA algorithm

I'm trying to figure out how to make a supercover DDA algorithm. Or in other words, a DDA algorithm that will cover ALL grid points crossed by a line. See the image below.
The image was drawn by me and might not be 100% accurate but it shows the general idea. I also want to note the examples on the lower half of the image do not have integer start and end coordinates, this is necessary.
If you need to know, I intend to use this for line of sight ray casting.
I'm capable of implementing a typical DDA algorithm, but my problem is, how can I modify it to cover all points?
Thanks!
My current implementation of the DDA algorithm in Lua
function dline(x0,y0, x1,y1) -- floating point input
local dx = x1-x0
local dy = y1-y0
local s = math.max(math.abs(dx),math.abs(dy))
dx = dx/s
dy = dy/s
local x = x0
local y = y0
local i = 0
return function() -- iterator intended for a for loop
if i <= s then
local rx,ry = x,y
x = x+dx
y = y+dy
i = i+1
return rx,ry
end
end
end
Sorry, I don't ask questions too often, mainly because I'm not that good. But I'll tell you what I am good at! Solving my own problem! :D
As a note, the image in my question shows the lines crossing diagonals if the line passes through a point precisely, this algorithm does not, but after some thought, crossing diagonals is not desirable for me.
Thanks to this article I found.
Here's the new implementation
function line(x0,y0, x1,y1)
local vx,vy = x1-x0, y1-y0 -- get the differences
local dx = math.sqrt(1 + (vy/vx)^2) -- length of vector <1, slope>
local dy = math.sqrt(1 + (vx/vy)^2) -- length of vector <1/slope, 1>
local ix,iy = math.floor(x0), math.floor(y0) -- initialize starting positions
local sx,ex -- sx is the increment direction
-- ex is the distance from x0 to ix
if vx < 0 then
sx = -1
ex = (x0-ix) * dx
else
sx = 1
ex = (ix + 1-x0) * dx -- subtract from 1 instead of 0
-- to make up for flooring ix
end
local sy,ey
if vy < 0 then
sy = -1
ey = (y0-iy) * dy
else
sy = 1
ey = (iy + 1-y0) * dy
end
local done = false
local len = math.sqrt(vx^2 + vy^2)
return function()
if math.min(ex,ey) <= len then
local rx,ry = ix,iy
if ex < ey then
ex = ex + dx
ix = ix + sx
else
ey = ey + dy
iy = iy + sy
end
return rx,ry
elseif not done then -- return the final two coordinates
done = true
return ix,iy
end
end
end
You can do it in the same time complexity as a normal dda algorithm by simply adding a few checks on adjacent squares.

How to calculate center of gravity in grid?

Given a grid (or table) with x*y cells. Each cell contains a value. Most of these cells have a value of 0, but there may be a "hot spot" somewhere on this grid with a cell that has a high value. The neighbours of this cell then also have a value > 0. As farer away from the hot spot as lower the value in the respective grid cell.
So this hot spot can be seen as the top of a hill, with decreasing values the farer we are away from this hill. At a certain distance the values drop to 0 again.
Now I need to determine the cell within the grid that represents the grid's center of gravity. In the simple example above this centroid would simply be the one cell with the highest value. However it's not always that simple:
the decreasing values of neighbour cells around the hot spot cell may not be equally distributed, or a "side of the hill" may fall down to 0 sooner than another side.
there is another hot spot/hill with values > 0 elsewehere within the grid.
I could think that this is kind of a typical problem. Unfortunately I am no math expert so I don't know what to search for (at least I have not found an answer in Google).
Any ideas how can I solve this problem?
Thanks in advance.
You are looking for the "weighted mean" of the cell values. Assuming each cell has a value z(x,y), then you can do the following
zx = sum( z(x, y) ) over all values of y
zy = sum( z(x, y) ) over all values of x
meanX = sum( x * zx(x)) / sum ( zx(x) )
meanY = sum( y * zy(y)) / sum ( zy(y) )
I trust you can convert this into a language of your choice...
Example: if you know Matlab, then the above would be written as follows
zx = sum( Z, 1 ); % sum all the rows
zy = sum( Z, 2 ); % sum all the columns
[ny nx] = size(Z); % find out the dimensions of Z
meanX = sum((1:nx).*zx) / sum(zx);
meanY = sum((1:ny).*zy) / sum(zy);
This would give you the meanX in the range 1 .. nx : if it's right in the middle, the value would be (nx+1)/2. You can obviously scale this to your needs.
EDIT: one more time, in "almost real" code:
// array Z(N, M) contains values on an evenly spaced grid
// assume base 1 arrays
zx = zeros(N);
zy = zeros(M);
// create X profile:
for jj = 1 to M
for ii = 1 to N
zx(jj) = zx(jj) + Z(ii, jj);
next ii
next jj
// create Y profile:
for ii = 1 to N
for jj = 1 to M
zy(ii) = zy(ii) + Z(ii, jj);
next jj
next ii
xsum = 0;
zxsum = 0;
for ii = 1 to N
zxsum += zx(ii);
xsum += ii * zx(ii);
next ii
xmean = xsum / zxsum;
ysum = 0;
zysum = 0;
for jj = 1 to M
zysum += zy(jj);
ysum += jj * zy(ii);
next jj
ymean = ysum / zysum;
This Wikipedia entry may help; the section entitled "A system of particles" is all you need. Just understand that you need to do the calculation once for each dimension, of which you apparently have two.
And here is a complete Scala 2.10 program to generate a grid full of random integers (using dimensions specified on the command line) and find the center of gravity (where rows and columns are numbered starting at 1):
object Ctr extends App {
val Array( nRows, nCols ) = args map (_.toInt)
val grid = Array.fill( nRows, nCols )( util.Random.nextInt(10) )
grid foreach ( row => println( row mkString "," ) )
val sum = grid.map(_.sum).sum
val xCtr = ( ( for ( i <- 0 until nRows; j <- 0 until nCols )
yield (j+1) * grid(i)(j) ).sum :Float ) / sum
val yCtr = ( ( for ( i <- 0 until nRows; j <- 0 until nCols )
yield (i+1) * grid(i)(j) ).sum :Float ) / sum
println( s"Center is ( $xCtr, $yCtr )" )
}
You could def a function to keep the calculations DRYer, but I wanted to keep it as obvious as possible. Anyway, here we run it a couple of times:
$ scala Ctr 3 3
4,1,9
3,5,1
9,5,0
Center is ( 1.8378378, 2.0 )
$ scala Ctr 6 9
5,1,1,0,0,4,5,4,6
9,1,0,7,2,7,5,6,7
1,2,6,6,1,8,2,4,6
1,3,9,8,2,9,3,6,7
0,7,1,7,6,6,2,6,1
3,9,6,4,3,2,5,7,1
Center is ( 5.2956524, 3.626087 )

Resources