I am using pygame, python3.9, I want to make to return which side(rect1) is collided with rect2.
I've already tried this but it dosen't work. I just want internal module and pygame.(sorry for bad english)
def side(rect1, rect2):
direction = ""
if rect1.midtop[1] > rect2.midtop[1]:
direction = "top"
if rect1.midleft[0] > rect2.midleft[0]:
direction = "left"
if rect1.midright[0] < rect2.midright[0]:
direction = "right"
if rect1.midbottom[1] < rect2.midbottom[1]:
direction = "bottom"
return direction
The side of the collision depends on the relative moving direction. The side of the collision depends on the relative movement of rect1 and rect2.
Anyway, you can estimate the side by calculating the difference in object position and finding the side with the minimum distance:
dr = abs(rect1.right - rect2.left)
dl = abs(rect1.left - rect2.right)
db = abs(rect1.bottom - rect2.top)
dt = abs(rect1.top - rect2.bottom)
if min(dl, dr) < min(dt, db):
direction = "left" if dl < dr else "right"
else:
direction = "bottom" if db < dt else "top"
Related
As a part of the Greiner-Hormann algorithm for polygon-clipping (described here), there is this subroutine:
In image form:
And transcribed (attempted):
intersect(P1,P2,Q1,Q2,alphaP,alphaQ)
WEC_P1 = <P1 - Q1 | (Q2 - Q1)⊥>
WEC_P2 = <P2 - Q1 | (Q2 - Q1)⊥>
if (WEC_P1*WEC_P2 <= 0)
WEC_Q1 = <Q1 - P1 | (P2 - P1)⊥>
WEC_Q2 = <Q2 - P1 | (P2 - P1)⊥>
if (WEC_Q1*WEC_Q2 <= 0)
alphaP = WEC_P1/(WEC_P1 - WEC_P2)
alphaQ = WEC_Q1/(WEC_Q1 - WEC_Q2)
return(true); exit
end if
end if
return(false)
end intersect
Which I don't understand at all. The explanation in the document mentions these window edge coordinates, but I don't know what they are and couldn't find any info on them except this slideshow, that doesn't go very much in depth.
Could someone give me a more detailed explanation on what those "wec"s are, and how are they useful in finding the intersection point of two line segments?
My understanding of window edge coordinates, based on the presentation linked in the question, is that they are a signed distance from a point to a line. That is, a scalar whose absolute value is the distance from the point to the line, and is positive if the point and the origin are on the opposite sides of the line, negative if they are on the same side.
How you calculate that distance, and why it works, I can't explain it in formal terms, but this video by Casey M. can point you in the right direction. Use it to understand how the dot product relate to the lengths of the two input vectors and come back. You can use this image as a reference:
To check if two points are on the opposite sides of a line, just check whether their wecs have the same sign. Do that for both sets of points and line, and you know if the lines are intersecting.
How do you find those alpha values? Well, for the line defined by p1 and p2, you are basically looking for a percentage that describes how much of the length of p1-p2 you should take to place the new point; and that's exactly what those instructions are doing.
Note that in the picture, wec_p1 > 0 and wec_p2 < 0 so (wec_p1 - wec_p2) > 0. Try to convince yourself that those last two assignments are equivalent to that a/b in the picture.
Here's my version of the pseudocode, with type annotations:
lines_intersect :: (p1: Vector2, p2: Vector2, q1: Vector2, q2: Vector2) -> bool, float, float {
intersection_found: bool = false;
p_alpha: float = 0;
q_alpha: float = 0;
q_normal: Vector2 = { q2.y - q1.y, q1.x - q2.x };
p1_wec: float = dot_product(q_normal, p1 - q1);
p2_wec: float = dot_product(q_normal, p2 - q1);
if p1_wec * p2_wec <= 0 {
p_normal: Vector2 = { p2.y - p1.y, p1.x - p2.x };
q1_wec: float = dot_product(p_normal, q1 - p1);
q2_wec: float = dot_product(p_normal, q2 - p1);
if q1_wec * q2_wec <= 0 {
intersection_found = true;
p_alpha = p1_wec / (p1_wec - p2_wec);
q_alpha = q1_wec / (q1_wec - q2_wec);
}
}
return intersection_found, p_alpha, q_alpha;
}
I have a function that detects if a ray is intersecting an object, but it works with a radius around the center of the object, I want it to work with a bounding box, I want to give it 2 Vector3D of the bounding box, and one vector of the origin of the ray and one of the direction of the ray, and it will calculate if there is an intersection, can anyone help me with that? what is the mathematical formula for this?
intersectRay(origin:Vector3D, dir:Vector3D):
Found the solution.
1. I use a bounding box of 8 points, each for each corner.
2. I used this function to give each point a location of x and y on a 2D plain this way I turned the 3D problem into a 2D problem, the x and y are really the horizontal angle of the point relative to the camera position and the vertical angle relative to the camera position point:
public function AngleBetween2vectors(v1:Vector3D,v2:Vector3D):Point
{
var angleX:Number = Math.atan2(v1.x-v2.x,v1.z-v2.z);
angleX = angleX*180/Math.PI;
var angleY:Number = Math.atan2(v1.y-v2.y,v1.z-v2.z);
angleY = angleY*180/Math.PI;
return new Point(angleX,angleY);
}
Then I use a convex hull algorithm to delete the point that are not part of the external outline polygon which marks the place of the object on the screen, can be found on the net, make sure the bounding box doesn't contain duplicate points like if you have a flat plain with no depth, this can cause problem for the algorithm, so when you create the bounding box clean them out.
Then I use this algorithm to determine if the point of the mouse click falls within this polygon or outside of it:
private function pnpoly( A:Array,p:Point ):Boolean
{
var i:int;
var j:int;
var c:Boolean = false;
for( i = 0, j = A.length-1; i < A.length; j = i++ ) {
if( ( ( A[i].y > p.y ) != ( A[j].y > p.y ) ) &&
( p.x < ( A[j].x - A[i].x ) * ( p.y - A[i].y ) / ( A[j].y - A[i].y ) + A[i].x ) )
{
c = !c;
}
}
return c;
}
Then I measure the distance to the object and pick the closest one to the camera position, using this function:
public function DistanceBetween2Vectors(v1:Vector3D,v2:Vector3D):Number
{
var a:Number = Math.sqrt(Math.pow((v1.x-v2.x),2)+Math.pow((v1.y-v2.y),2));
var b:Number = Math.sqrt(Math.pow((v1.z-v2.z),2)+Math.pow((v1.y-v2.y),2));
return Math.sqrt(Math.pow(a,2)+Math.pow(b,2));
}
I'm sure there are more efficient ways, but this way is an interesting one, and it's good enough for me, I like it because it is intuitive, I don't like to work with abstract mathematics, it's very hard for me, and if there is a mistake, it's very hard to find it. If anyone has any suggestions on how I can make it more efficient, I'll be happy to hear them.
I have 2 sprite, spriteA and spriteB, one is added to HelloWord Layer and the other added to a node:
node = Node::create();
this->addChild(node);
spriteA = Sprite::create("spriteA.png");
node->addChild(spriteA);
spriteB = Sprite::create("spriteB.png");
this->addChild(spriteB);
Then I need to move the node to spriteB center, and keep the spriteA position from the spriteB:
//get screen position of spriteA and (maybe not) position of spriteA from spriteB
Vec2 point = center->convertToWorldSpace(spriteA->getPosition());
Vec2 position = Vec2(point.x - SpriteB->getPositionX(), point.y - spriteB->getPositionY());
node->setPosition(spriteB->getPosition());
spriteA->setPosition(position);
But I can get the good position of the spriteA from the spriteB, someone can help please?
i tried this code, and it works
auto posB = spriteB->getPosition();
auto posA = spriteA->getPosition();
auto dis = node->getPosition() - posB;
node->setPosition(posB);
spriteA->setPosition(posA + dis);
if still not work, maybe you need to set node contentsize and anchorpoint
Could someone please explain me what are w.r.t. coordinates? or at least direct me to a place that explains what they are? I've being searching for two days or so and all that I found is tutorials on how are they used but not what they actually are or even what wrt stand for.
These tutorials take the assumption I already know what they are which is stressful because I've never heard of them.
I'm working in as3 trying to do some parametric surfaces using pixel particles and I understand these are kind of useful while moving the particles around.
This is the relevant function where they are used as u,v and w, where p is a single particle that also contains xyz values that are not being modified.
function onEnter(evt:Event):void {
dphi = 0.015*Math.cos(getTimer()*0.000132);
dtheta = 0.017*Math.cos(getTimer()*0.000244);
phi = (phi + dphi) % pi2;
theta = (theta + dtheta) % pi2;
cost = Math.cos(theta);
sint = Math.sin(theta);
cosp = Math.cos(phi);
sinp = Math.sin(phi);
//We calculate some of the rotation matrix entries here for increased efficiency:
M11 = cost*sinp;
M12 = sint*sinp;
M31 = -cost*cosp;
M32 = -sint*cosp;
p = firstParticle;
//////// redrawing ////////
displayBitmapData.lock();
//apply filters pre-update
displayBitmapData.colorTransform(displayBitmapData.rect,darken);
displayBitmapData.applyFilter(displayBitmapData, displayBitmapData.rect, origin, blur);
p = firstParticle;
do {
//Calculate rotated coordinates
p.u = M11*p.x + M12*p.y + cosp*p.z;
p.v = -sint*p.x + cost*p.y;
p.w = M31*p.x + M32*p.y + sinp*p.z;
//Calculate viewplane projection coordinates
m = fLen/(fLen - p.u);
p.projX = p.v*m + projCenterX;
p.projY = p.w*m + projCenterY;
if ((p.projX > displayWidth)||(p.projX<0)||(p.projY<0)||(p.projY>displayHeight)||(p.u>uMax)) {
p.onScreen = false;
}
else {
p.onScreen = true;
}
if (p.onScreen) {
//we read the color in the position where we will place another particle:
readColor = displayBitmapData.getPixel(p.projX, p.projY);
//we take the blue value of this color to represent the current brightness in this position,
//then we increase this brightness by levelInc.
level = (readColor & 0xFF)+levelInc;
//we make sure that 'level' stays smaller than 255:
level = (level > 255) ? 255 : level;
/*
We create light blue pixels quickly with a trick:
the red component will be zero, the blue component will be 'level', and
the green component will be 50% of the blue value. We divide 'level' in
half using a fast technique: a bit-shift operation of shifting down by one bit
accomplishes the same thing as dividing by two (for an integer output).
*/
//dColor = ((level>>1) << 8) | level;
dColor = (level << 16) | (level << 8) | level;
displayBitmapData.setPixel(p.projX, p.projY, dColor);
}
p = p.next;
} while (p != null)
displayBitmapData.unlock();
}
This is the example I'm using http://www.flashandmath.com/flashcs4/light/
I kinda understand how are they used but I don't get why.
Thanks in advance.
PD: kind of surprised there is not even a tag related to it.
In that Particle3D.as class linked, they have:
//coords WRT viewpoint axes
public var u:Number;
public var v:Number;
public var w:Number;
From the code example you posted to the question it becomes clear that coords WRT viewpoint axes means coordinates with respect to viewpoint axes, since the code is doing exactly that .
What they are doing is a Camera (or Viewing) Transformation, where the Particle's world coordinates (x,y,z) is transformed from the world coordinate system to coordinates in the camera (or view) coordinate system (u,v,w).
(x,y,z) are the coordinates of the particle in the world coordinate system
(u,v,w) are the coordinates of the particle in the camera coordinate system
For example, the world coordinate system might have an origin at (0,0,0) with the camera positioned at something like (5,3,6) with an lookat vector of (1,0,0) and up vector of (0,1,0).
I am making a flash game and I have a game character similar to this
http://us.123rf.com/400wm/400/400/chudtsankov/chudtsankov1004/chudtsankov100400927/6906625-cartoon-character-mobster-carries-weapon.jpg
The character is able to shoot when facing left,and the bullet is shot diagonally from the direction of the gun.
However, when my character faces right, the bullet is shot from the back of the head rather than the gun itself. I did realise that when the character is facing right, the registration point is on the gun but when facing left, the registration point is on the back of her head. Could that be a problem? And how do i overcome this?
Here is my code
function shootBulletBoy():void {
var fire:myBullet2 = new myBullet2();
fire.x = GirlHero.x;
fire.y = GirlHero.y;
addChild(fire);
fire.addEventListener(Event.ENTER_FRAME, moveBullet2);
}
function moveBullet2(e:Event):void {
if (GirlHero.currentLabel == ('left')){
e.currentTarget.x += Math.cos(rads) * speed;
e.currentTarget.y += Math.sin(rads) * speed;
e.currentTarget.rotation = 265;
}
if (GirlHero.currentLabel == ('right')){
e.currentTarget.x += Math.cos(radss) * speedd;
e.currentTarget.y += Math.sin(radss) * speedd;
}}
Another issue that I am having is that when my character is facing left and shoots, the gun shoots in the left direction however if the character turns right whilst the bullet is still up in the air, my bullet all of a sudden turns in the rights direction. I don't know why its doing this.
Sorry if im asking too much. You dont have to answer both my problems, a little help would do :)
Thank you
To fix your issue with the origin of your players shoot has to do with:
fire.x = GirlHero.x;
fire.y = GirlHero.y;
You are right. the registration point will be an issue. To fix this use an if statement much like your moveBullet2 function.
if (GirlHero.currentLabel == ('left')){
fire.x = GirlHero.x + leftXOffset;
fire.y = GirlHero.y + leftYOffset;
}else if (GirlHero.currentLabel == ('right')){
fire.x = GirlHero.x + rightXOffset;
fire.y = GirlHero.y + rightYOffset;
}
The offset values will need to be played with based on you character.
For you bullet shooting problem.
your MoveBullet2() function is updating direction of you bullets while they are in the air.
Once a bullet is shot, you do not want to change its direction.
Instead in your myBullet2 Class (or in code inside myBullet2 MovieClip)
create variables rads and rotation. Then set them when you create a bullet. Then in your moveBullet2() youd have:
var b:myBullet2 = myBullet2(e.currentTarget);
b.x += Math.cos(b.rads) * speedd;
b.y += Math.sin(b.rads) * speedd;
and where you create bullet would add:
fire.rads = rads;
fire.rotation = rot;
which these values would be based on the direction character facing and where the mouse was pointing.