I am doing a rubiks cube simulator. To make the sides turn, I have a collider on each of the sides, and I make the colliders parent everything inside them on click and then just turn the side.
To get every object inside the colliders, I use Physics.OverlapBox, and put every object except the other sides inside a list like this:
public List<GameObject> children = new List<GameObject>();
private void Awake()
{
UpdateCubes();
}
void UpdateCubes()
{
Mesh mesh = GetComponent<MeshFilter>().mesh;
children.Clear();
foreach (Collider child in Physics.OverlapBox(transform.localPosition,
Vector3.Scale(mesh.bounds.size, transform.lossyScale) / 2, transform.rotation))
{
if (!child.transform.CompareTag("Side"))
{
children.Add(child.gameObject);
}
}
}
Here is the problem:
It seems like Physics.OverlapBox is way too big, because it gets every piece of the cube and some weird missing gameobjects, as seen here:
I have tried to change transform.localScale / 2 to transform.lossy Scale / 2 but it does'nt work. What should I do?
Both kinds of transform scale (lossy and local) are multipliers not units, while OverlapBox is using units for it's position and size. If your scale is 1 and the mesh size is 0.1, then the object takes up 0.1 units, not 1. To be sure you're accurate, you want to use Mesh.bounds.size and multiply that by the transform.lossyScale. This will give you the accurate size in units.
I got it working! The pieces from other sides were overlapping with other sides because they were so close together. I fixed it by putting more offset between them.
Related
I need to simulate the movement of a row(oar). The oar object is loaded into eclipse with the min3D library which works with openGL.
At this moment, I make the oar move in the 3 axis x, y and z, but I'm not able to control this movement and to make the oar move in the desired way.
(Don't take care of the values, aren't real values)
This is the class which loads the oar, places it in the screen and moves it:
public class Obj3DView extends RendererFragment {
private Object3dContainer rowObject3D;
/** Called when the activity is first created. */
#Override
public void initScene() {
scene.lights().add(new Light());
scene.lights().add(new Light());
Light myLight = new Light();
myLight.position.setZ(150);
scene.lights().add(myLight);
IParser myParser = Parser.createParser(Parser.Type.OBJ, getResources(), "com.masermic.rowingsoft:raw/row_obj",true);
myParser.parse();
rowObject3D = myParser.getParsedObject();
rowObject3D.position().x = rowObject3D.position().y = rowObject3D.position().z = 0;
rowObject3D.scale().x = rowObject3D.scale().y = rowObject3D.scale().z = 0.28f;
scene.addChild(rowObject3D);
}
//THIS MAKES THE OAR MOVE
#Override
public void updateScene() {
rowObject3D.rotation().x += 1; //pitch
rowObject3D.rotation().z += 1; //roll
rowObject3D.rotation().y += 0.5; //yaw
}
roation() method definition: X/Y/Z euler rotation of object, using Euler angles. Units should be in degrees, to match OpenGL usage.
So the question is about how could I define the values that make the oar simulate a real movement?
This looks more like a mathematics question.
I'll present some general tips;
On positioning:
The fixed point of the oar is where the oar is held on the boat, so the oar's rotation is relative to that point, not the center of the oar.
And on top of that, the boat is moving, so is the oar's "fixed" point.
The order for positioning should be:
Translate to the boat position.
Translate the oar so it's center is relative to the correct spot of the boat.
Apply the oar rotation.
Draw it.
On animation:
It will be easier to animate if you alter your model so the origin is at the point where the oar is fixed, but it may complicate other animations/calculae if you later pretend to do more complex manipulations on the oar.
Interpolation of Euler rotation is a mess, I suggest quartenions. You can grab the angles from that nice picture and interpolate. (if you need Euler, still, you can convert the end result to Euler)
For simple animations, (say you just want the oar to repeatedly rotate in some pattern), hardly you will find a better method then key-frames, that is, create a list of coordinates/angles along the path you want the oar to do, and iterate through them, interpolating.
With enough points, a simple linear interpolation will do just fine.
I have some collision detection working when my player hits an object. But this only works when my players x & y co-ordinates hit my marker (which is the centre of my character).
Would making a method returning a vector of all of the coordinates that the players texture cover work and what is the best way to implement this?
This is being done in c++ creating a top down game
There are many ways to do it, most simply is probably(depending on you use of classes etc).
This is the simplest, but no where near the best, or infact very good at all. This way means changing your "marker" to the bottom left of the rectangle.
void collisions()
{
//check if the x-coord is between the furthest left and furthest right x coords
if(rect.Getx() > someObject.Getx() && rect.Getx() < someObject.Getx() + someObject.GetWidth())
{
rect.SetMoveSpeed(0);
}
if(rect.Gety() > someObject.Gety() && rect.Gety() < someObject.Gety() + someObject.GetHeight())
{
rect.setMoveSpeed(0);
}
}
You would then have to set the move speed to normal when it is not colliding. That could be done with an else after each if, setting the move speed again. This is a quick fix and is not recommended for use in a game you plan to distribute anywhere.
I'm using Cocos2D for iPhone to build up a game.I have a grid on the screen drawn by horizontal and vertical lines.(I did it with CCDrawNode) As you might guess there're lots of intersection points in there, I mean the points where horizontal and vertical lines intersect. With every touchBegan-Moved-Ended routine I draw a line, a bolder and different color line. In touchesMoved method I need to find the intersection point nearest to the current end point of the line and stick the line end to that point. How can I do that? I have one idea in my mind which is to add all the intersection points to an array when drawing the grid, iterate through that array and find the closest one. But I think this is not the best approach. You have any better ideas?
Assuming it is a normal grid with evenly spaced lines (e.g. every 10 pixels apart), you are much better off using a formula to tell you where an intersection should be.
E.g. given end point X/Y of 17,23, then x(17)/x-spacing(10) = 1.7, rounds to 2. 2*x-spacing = 20. y/y-spacing=2.3 -> 2*20 = 20. Thus your intersection is 20,20.
EDIT: more detailed example, in C# as that's what I use, if I get time I'll write an Objective-C sample
// defined somewhere and used to draw the grid
private int _spacingX = 10;
private int _spacingY = 10;
public Point GetNearestIntersection(int x, int y)
{
// round off to the nearest vertical/horizontal line number
double tempX = Math.Round((double)x / _spacingX);
double tempY = Math.Round((double)y / _spacingY);
// convert back to pixels
int nearestX = (int)tempX * _spacingX;
int nearestY = (int)tempY * _spacingY;
return new Point(nearestX, nearestY);
}
NOTE: the code above is left quite verbose to help you understand, you could easily re-write it to be cleaner
Ok, I'd like to start off by saying that I know I'm not actually moving the camera, but it's easier to explain that way.
My problem is that I'm trying to move the camera with my character in a top down 2d rpg, and I can't find the correct way to do it. I know about glTranslate() but then I can only use a speed instead of an x and y coordinate. I'm not sure how to move the camera keeping the delta in mind. I don't even know if glTranslate() is even the method I should be using.
In case I'm not making any sense (which is very likely), here's some of my code.
My test while loop:
while(!Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)&&!Display.isCloseRequested())
{
glClear(GL11.GL_COLOR_BUFFER_BIT);
delta=getDelta();
update(delta);
glTranslatef(speedx, speedy, 0);
level1.checkCurrent(x, y);
level1.draw();
Display.update();
Display.sync(60);
}
Here is where I set the speed:
if(Keyboard.isKeyDown(Keyboard.KEY_DOWN))
{
y+=0.5*delta;
screenY+=0.5*delta;
speedy=(int) (-0.5*delta);
direction=2;
}
else if(Keyboard.isKeyDown(Keyboard.KEY_UP))
{
y-=0.5*delta;
screenY-=0.5*delta;
speedy=(int) (0.5*delta);
direction=8;
}
else
speedy=0;
Right now you're treating OpenGL as if it were a scene graph. However OpenGL is only meant to draw things on the screen. Whatever you do, you should always think about your problem in a way, as if all the rest of the infrastructure wasn't there.
You want to accelerate an object? Well, then you need to increment some speed variable over time and that speed variable multiplied by time adds to the position. In essence Newton's laws of motion:
a = dv/dt => v = a*t + v_0
v = dr/dt => r = v*t + r_0 = a*t² + v_0*t + r_0
This you evaluate for each of your objects. Then when drawing the animation, you use the state to place the object geometry accordingly.
I'm having a lot of trouble detecting collisions in a zero-G space game. Hopefully this image will help me explain:
http://i.stack.imgur.com/f7AHO.png
The white rectangle is a static body with a b2PolygonShape fixture attached, as such:
// Create the line physics body definition
b2BodyDef wallBodyDef;
wallBodyDef.position.Set(0.0f, 0.0f);
// Create the line physics body in the physics world
wallBodyDef.type = b2_staticBody; // Set as a static body
m_Body = world->CreateBody(&wallBodyDef);
// Create the vertex array which will be used to make the physics shape
b2Vec2 vertices[4];
vertices[0].Set(m_Point1.x, m_Point1.y); // Point 1
vertices[1].Set(m_Point1.x + (sin(angle - 90*(float)DEG_TO_RAD)*m_Thickness), m_Point1.y - (cos(angle - 90*(float)DEG_TO_RAD)*m_Thickness)); // Point 2
vertices[2].Set(m_Point2.x + (sin(angle - 90*(float)DEG_TO_RAD)*m_Thickness), m_Point2.y - (cos(angle - 90*(float)DEG_TO_RAD)*m_Thickness)); // Point 3
vertices[3].Set(m_Point2.x, m_Point2.y); // Point 3
int32 count = 4; // Vertex count
b2PolygonShape wallShape; // Create the line physics shape
wallShape.Set(vertices, count); // Set the physics shape using the vertex array above
// Define the dynamic body fixture
b2FixtureDef fixtureDef;
fixtureDef.shape = &wallShape; // Set the line shape
fixtureDef.density = 0.0f; // Set the density
fixtureDef.friction = 0.0f; // Set the friction
fixtureDef.restitution = 0.5f; // Set the restitution
// Add the shape to the body
m_Fixture = m_Body->CreateFixture(&fixtureDef);
m_Fixture->SetUserData("Wall");[/code]
You'll have to trust me that that makes the shape in the image. The physics simulation works perfectly, the player (small triangle) collides with the body with pixel perfect precision. However, I come to a problem when I try to determine when a collision takes place so I can remove health and what-not. The code I am using for this is as follows:
/*------ Check for collisions ------*/
if (m_Physics->GetWorld()->GetContactCount() > 0)
{
if (m_Physics->GetWorld()->GetContactList()->GetFixtureA()->GetUserData() == "Player" &&
m_Physics->GetWorld()->GetContactList()->GetFixtureB()->GetUserData() == "Wall")
{
m_Player->CollideWall();
}
}
I'm aware there are probably better ways to do collisions, but I'm just a beginner and haven't found anywhere that explains how to do listeners and callbacks well enough for me to understand. The problem I have is that GetContactCount() shows a contact whenever the player body enters the purple box above. Obviously there is a rectangular bounding box being created that encompasses the white rectangle.
I've tried making the fixture an EdgeShape, and the same thing happens. Does anyone have any idea what is going on here? I'd really like to get collision nailed so I can move on to other things. Thank you very much for any help.
The bounding box is an AABB (axis aligned bounding box) which means it will always be aligned with the the Cartesian axes. AABBs are normally used for broadphase collision detection because it's a relatively simple (and inexpensive) computation.
You need to make sure that you're testing against the OBB (oriented bounding box) for the objects if you want more accurate (but not pixel perfect, as Micah pointed out) results.
Also, I agree with Micah's answer that you will most likely need a more general system for handling collisions. Even if you only ever have just walls and the player, there's no guarantee that which object will be A and which will be B. And as you add other object types, this will quickly unravel.
Creating the contact listener isn't terribly difficult, from the docs (added to attempt to handle your situation):
class MyContactListener:public b2ContactListener
{
private:
PlayerClass *m_Player;
public:
MyContactListener(PlayerClass *player) : m_Player(player)
{ }
void BeginContact(b2Contact* contact)
{ /* handle begin event */ }
void EndContact(b2Contact* contact)
{
if (contact->GetFixtureA()->GetUserData() == m_Player
|| contact->GetFixtureB()->GetUserData() == m_Player)
{
m_Player->CollideWall();
}
}
/* we're not interested in these for the time being */
void PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
{ /* handle pre-solve event */ }
void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse)
{ /* handle post-solve event */ }
};
This requires you to assign m_Player to the player's fixture's user data field. Then you can use the contact listener like so:
m_Physics->GetWorld()->SetContactListener(new MyContactListener(m_Player));
How do you know GetFixtureA is the player and B is the wall? Could it be reversed? Could there be an FixtureC? I would think you would need a more generic solution.
I've used a similar graphics framework (Qt) and it had something so you could grab any two objects and call something like 'hasCollided' which would return a bool. You could get away with not using a callback and just call it in the drawScene() or check it periodically.
In Box2D the existence of a contact just means that the AABBs of two fixtures overlaps. It does not necessarily mean that the shapes of the fixtures themselves are touching.
You can use the IsTouching() function of a contact to check if the shapes are actually touching, but the preferred way to deal with collisions is to use the callback feature to have the engine tell you whenever two fixtures start/stop touching. Using callbacks is much more efficient and easier to manage in the long run, though it may be a little more effort to set up initially and there are a few things to be careful about - see here for an example: http://www.iforce2d.net/b2dtut/collision-callbacks