I'm trying to implement 'lever' into my android game, here's image showing what do I want, showing how does it work:
1)
2)
I managed to do basic of it by using joint:
final RevoluteJointDef revoluteJointDef = new RevoluteJointDef();
revoluteJointDef.initialize(anchorBody, movingBody, anchorBody.getWorldCenter());
revoluteJointDef.enableLimit = true;
revoluteJointDef.upperAngle = MathUtils.degToRad(40);
revoluteJointDef.lowerAngle = MathUtils.degToRad(-40);
physicsWorld.createJoint(revoluteJointDef);
And it works, I can move lever stick in left/right direction, and as it should you can not exceed proper angle, so this part is done. But now I'm looking for a way, when execute actions after moving this lever (for example open some doors/gate)
Here's my basic idea, how to check which part of the stick has been touched by player (left or right) by creating stick's body with this way:
So explaining, by adding 2 sensors, one on left side and one on right side, so in contact listener I would check which side has been touched.
But still I have no idea how to check if action should be performed, I know I could check on every update if stick angle is 40 or -40, but is it effective way? Or maybe there is better? I will be greatly thankful for any tips! Thanks
You don't need to worry about efficiency here, the performance penalty for checking the angle is absolutely negligible. I measured the times needed to get the angle of a Sprite and a Body using the following code snippet:
double testEnd;
double testStart;
testStart = System.nanoTime();
for (int i = 0; i<1000000; i++) {doStuff()}
testEnd = System.nanoTime();
Log.v("speed test", "it takes "+ (testEnd - testStart)/1000000 + " nanoseconds");
So, on Desire Z it takes only 157 ns to find the angle of a Sprite and 393 ns to do the same with Body. It is also much simpler than using contact listeners. Just a side note, the angles of Sprites can be outside of (-360, +360) degrees if you rotate the Sprite.
Both the methods you mention would work, it's just a matter of which you find more convenient. It also seems like you already understand the implementation, so I don't think anyone could answer this question any better than to say, 'whichever suits you better'.
Putting a sensor at each end of the lever's range and using a contact listener to detect when the lever touches them is the most 'correct' way. It conveniently gives you events both when the lever touches the sensors and when they stop touching, but it's a little more work to set up.
Checking the joint angle after every time step will work fine too, but you'll need to compare the angle with the value in the previous step if you want to detect a start/finish touching 'event'. If you want a lever that can give continuous values (eg. speed control for some other object) instead of a simple on/off switch then you would be better off with this method.
Related
I'm in the process of creating a sidescrolling action game where you play a wizard that can cast spells. The spells are Box2D bodies that start in the middle of your player (who is also a Box2D body) and go outward in the direction you clicked on the screen.
I have all the collision detection working to where the spells you cast don't collide with each other and they don't collide with you. This works more-or-less flawlessly -- except for one instance. The first spell I cast creates a collision with the player that causes a brief period of physical knockback. The spell's path is not affected otherwise, and I don't notice a major change in the player's position. The only reason I know there is knockback at all is because the camera I have following the player suddenly shakes in that instant (and I've gone through the contact listener to verify that these particular bodies are forming a contact).
This is not the case for subsequent spells that are spawned from the same position, and it doesn't seem to be a problem that is related to the player's move speed or the projectile's cast angle. It may have something to do with how Box2D initializes items, but I couldn't promise that.
Does anyone know how I could fix this?
As weston mentioned, some more code may be needed, but it does sound odd that "the first spell" does this, but subsequent spawnings don't. Do you reuse bodies for subsequent spawns?
In box2d if you create 2 bodies that occupy the same space they will "knockback" from each other so that they DON'T occupy the same space. This is by design, and only happens on creation. I'm sure this is what you're seeing. Why it doesn't happen "afterwards" may be dependent on your code.
Ways around this might be to set some of your fixtures as sensors for a bit (collisions are ignored), or when you create a body, set active=false (again, collisions ignored). By "for a bit" I mean you may have to write some code to move your spell, ignoring collisions, until your spell has "cleared" your wizard. Then remove the sensor or make it active so collisions are back in play.
But that may be overkill, figuring out the subtlety of subsequent "spans" vs. your first one may be a better use of effort.
I managed to figure out where the problem was and how to solve it, but I wasn't able to fight out why it was happening.
I was using an OrthographicCamera to lerp to my player's position.
position.x += (universe.entity_handler.player.parts[0].body.getPosition().x - position.x) * Gdx.graphics.getDeltaTime() *
position.y += (universe.entity_handler.player.parts[0].body.getPosition().y - position.y) * Gdx.graphics.getDeltaTime() * LERP + zoom * viewportHeight / WORLD_PLAYER_Y_SKEW;
And when I fixed this by removing all lerping, the jitter was gone.
position.x = universe.entity_handler.player.parts[0].body.getPosition().x;
position.y = universe.entity_handler.player.parts[0].body.getPosition().y;
I have zero idea why linear interpolation was causing spastic movements like that, but hey - I got it to work. Maybe I'll go back and revisit the problem later.
I started programming a game in java. I have Enemys and a Player, a basic 2D game, thats to get experience for the first time.
Now i wanted the Enemys to follow a path, which i can draw in to a "level editor".
I have a JPanel, a mouseMoveListener, and on click the Path2D starts saving the mouseMove Points to a Path2D.Double Object.
After that, i implemented the following method to make the enemys following this path:
public void forward(){
if(!pathIterator.isDone()){
pathIterator.currentSegment(current);
x = current[0];
y = current[1];
pathIterator.next();
}
else {
dead = true;
}
}
I think its clear what happens now: The Enemy is following, but the speed is that i moved the mouse with. So if i move to Mouse to fast, the enemy just.. "jumps" from one point to an other. To slow, its "sneaking" over that points. (And because im not an Robot, i cannot move the Mouse with the same speed ^^)
Talking of Robot: Yes, i could let a awt.Robot move my Mouse. But this isnt really possible too, because i have to draw complicated paths, which dont have any visible mathematics behind.
So, i want let this Enemys to move on this path with the same speed. My Problem: I don't know where to implement a "fix". I have 2 Ideas:
Maybe i could work on the Path creation: Instead of just adding the Points to the Path2D, maybe i could calculate points between the points where i moved to fast, or deleting points which are to near by each other. But: First, I don't know how to calculate this, (Is there any maths logic to achieve this?) And Second, when i do this i probably would'nt be able to change the speed of the enemys ingame, and that would be bad
The second idea i have, is to calculate the points between (oder the points to jump over), this should happen every frame, relative to the actual speed. But here im not experienced enough in maths to.
So, are that ways possible, and if yes, has someone an idea how to calculate this?
And, if not, what other possibilitys i have to achieve this?
Thank you, and sorry for the bad english!
All you need to do is define the speed of movement of the enemy inside the enemy class.
When it works out the next point to move to then create a direction vector by subtracting the current position from the new position.
Normalize the direction vector (so it is length 1) then multiply it by the speed and the tpf (time per frame).
Move by that amount instead of jumping to the next point.
(Note if the points are very close together or the framerate is low this can cause it to overshoot a bit, it should be fine though).
I was wondering how i can speed up whole game done with libgdx (for example after clicking a button). The way i have in my game is modify a timestep variable used in
world.step(TIMESTEP, VELOCITYITERATIONS, POSITIONITERATIONS);
but im now sure if it's a good idea. If there a any better way to archive that?
When using Box2D you can speed up your game by modifying the physics step. One problem is that you should use a constant steptime. I use the following code below in my games:
private float accumulator = 0;
private void doPhysicsStep(float deltaTime) {
// fixed time step
// max frame time to avoid spiral of death (on slow devices)
float frameTime = Math.min(deltaTime, 0.25f);
accumulator += frameTime;
while (accumulator >= Constants.TIME_STEP) {
WorldManager.world.step(Constants.TIME_STEP, Constants.VELOCITY_ITERATIONS, Constants.POSITION_ITERATIONS);
accumulator -= Constants.TIME_STEP;
}
}
This makes sure that your steptime is constant, but it's synchronized with the render loop. You could use that and call it like doPhysicsStep(deltaTime * speedup) (speedup is 1 by default, and maybe 1.5 after a button was pressed). This might probably result in not optimal results, but you could give it a try.
Otherwise you can go the hard way like it was suggested in the comments and invest more time by modifiying every place in your code where it is necessary (all forces need to be modified, which in many cases isn't as trivial as force * speedup, because in the real/physics world, not everything acts linear).
I'm having an issue with sprite movement, and I'm not sure how to deal with it.
When I set a destination for my player sprite (by clicking the screen), it sets the player moving in that direction. Unfortunately, the player sort of... oscillates. He sort of shivers along the path.
I've set up a test project using just graphics primitives (graphics.fillRect(x,y,w,h)), and its really easy to see. Here's a sort of example without using video/gifs:
My code looks like this
public void tick() {
if (InputHandler.leftClick.heldDown) {
dest.setLocation(InputHandler.leftClick.xPos, InputHandler.leftClick.yPos);
}
direction.setLocation(dest.getX() - position.x, dest.getY() - position.y);
direction.normalize();
position.add(direction.multiply(velocity));
}
This is a really really basic movement system because I'm having the same issues elsewhere and I wanted to work on them in a more controlled environment.
The weirdest part about this is that when the player arrives, he still just sits on one point, shivering madly.
Can anyone help?
There's a little discrepancy? between what you said, "clicking on the screen" and heldDown. Have you read about mouse event handlers? But I see that you want to go on a tick by tick basis. It would be more clear to have a boolean flag that alerts you if the path was changed. Then this segment would look like
if (leftclicked) {
dest.setLocation(InputHandler.leftClick.xPos, InputHandler.leftClick.yPos);
leftclicked = false;
}
...
Strictly, in physics, velocity is a vector. It has both direction and magnitude. If you intend this as simply a speed at which the thing can move, with instant turning, the next three lines should be fine, although the readability seems improvable. (You have to be sure of what all the helper methods are doing. I'd probably prefer to do whatever calculations needed right here in one place.)
However I suspect you do have velocity as something like vector. There is some notion of momentum in here. I think the multiply() method is implemented strangely. If it adds/combines the angle of velocity with the angle of direction behavior like this results. Having an aspect of momentum is cool but if desired you should really think how to do it.
Another explanation is that the code you've shown works as intended, inching the thing along the direction of the black line, but some other part of your code is messing with position. We weren't given a picture of what happens on arrival...
One more thing about readability. It's very important..."really really basic" things can be buggy swamps without simple organizing steps. I have to rewrite implementations several times because I get overeager and miss designs. It looks like you are doing well at my bane, the "one method/object does one thing (well)" principle but getting into trouble with...naming, of all things. Example: direction.setLocation() Now, directions do not have locations. Repeat: directions do not have locations. Also, directions don't need to be normalized - they don't have lengths.
Instead:
direction = new Direction(dx, dy);
position.add(direction.multiply(MOVEMENT_SPEED));//assuming constant speed
where
//sensible encapsulation of "direction"
class Direction {
double angle;//angle in degrees
//constructs a direction from cartesian coordinates
Direction(int x, int y){
angle = Math.toDegrees(Math.atan((double)y/x));
}
//create a vector of specified length in this direction
java.awt.Point multiply(double amt){
return new java.awt.Point(amt*Math.cos(angle), amt*Math.sin(angle))
}
...
}
Hmm long answer...please try for crystal clear code and questions in future! :)
I am developing an AI simulation of predator and prey. I would like to simulate the AI hiding behind obstacles, if it is being chased. But I am still trying to figure out the best way to implement this.
I was thinking along the lines of checking on which side of the obstacle the predator is on and trying to go on the opposite side. Maybe using the A* path finding algorithm to ensure that it gets there using the shortest path.
Now the main reason I am writing is in case somebody is able to point me in the right direction of implementing this (maybe somebody has done this before) or have any other good ideas how to implement it. I have never done anything like this before in terms of programming AI or making any game.
All the obstacles are either horizontal or vertical squares/rectangles.
Please note that the circle in red is the predator while the circle in green is the prey being chased.
I can't give any code off the top of my head, but I can tell you a few things:
First, you need to define the goal of this program. For this case, it is to get the AI to hide behind an obstacle, keeping the user and the AI on opposite sides whenever possible.
Next, you need to decide what needs to be done inside the code (without writing any real code) to accomplish this goal. For instance:
We need to determine what "zone" of the scene is considered "behind the obstacle"
Next, we need to determine a path for the AI to get to that zone without going through the obstacle.
Lastly, we need to add some sort of delay to this so the AI doesn't constantly change its mind for every pixel the user moves across the screen
This isn't per se an easy problem, but it is certainly achievable without breaking too much of a sweat. I'd recommend you find a way, even if it is slow and requires a ton of code, then write the code for it, and lastly refine. If you worry about refinement, then you never get any of the problem solved.
HINT: Determine a vector that points from the player to the middle of the obstacle. Then, multiply the vector by 2 and add it to the position of the player and that gives you a point on the other side of the obstacle (assuming it is a rectangle). Apply a Math.min() or Math.max() restrictor to the x and y values you get to keep the AI as close or far from the obstacle as you wish. That should be a decent start! :)
Update -- I decided to add some code!
// This assumes a few variables:
int obstacleCenterX, obstacleCenterY;
int aiX, aiY, aiWalkSpeed;
int predatorX, predatorY;
private void updateAIMovement() {
int slope_x = obstacleCenterX - predatorX;
int slope_y = obstacleCenterY - predatorY;
int destination_x = predatorX + (slope_x * 2);
int destination_y = predatorY + (slope_y * 2);
if(aiX != destination_x){
aiX += (slope_x / Math.abs(slope_x)) * aiWalkSpeed;
}
if(aiY != destination_y){
aiY += (slope_y / Math.abs(slope_y)) * aiWalkSpeed;
}
}
I have not tested anything at all, but I think this might be somewhat of a right path to take. I could have done A LOT to improve just that little code snippet, but I didn't (such as some trig to make sure the player moves at a true speed when going diagonally, etc...)
Hopefully this helps a little!
I would check if there is something crossing the direct line between x and each observer. If it is, x is hidden.