I'm making a platformer game. The jumping and movement are working, and now I want to program the collisions. I have a sort of idea as to how this will work:
I wasn't sure whether this question should be here or in the game dev site.
I have two Vector2's - velo and momentum (velo is the velocity). Both are (0, 0). The momentum is what's added to the velocity each frame.
Each frame, I first get the input. Momentum is increased and/or increased based on the keys pressed (e.g: if (Gdx.input.isKeyPressed(Keys.A)) { momentum.x -= speed; })
I then multiply the momentum by 0.15. This is so that it slows down.
After this, I multiply the velocity by 0.8.
Then, I add the momentum to the velocity, to increase the velocity, as
this is what actually moves the player.
I then add the velocity to the position of the player.
To apply the gravity, I add a gravity vector (0, -10) to the position of the player.
So I need to find a way to move the player, but not allowing it to overlap any part of the world. The world is made up of lots of Rectangle instances. The player's body is also an instance of Rectangle. Would it be easier to rewrite the collisions using Box2D? What I've tried is checking if the player overlaps any rectangles when it's moved, and if it will, not moving it. But this doesn't seem to take everything into account - sometimes it works, but other times, it stops before touching the world.
TL;DR: I want to make collisions of my player with a world which is stored as a grid of rectangles. How would I do this, as my player is also a Rectangle. Would it be easier to use Box2D?
This answer gives a good overview about the details of collision detection:
https://gamedev.stackexchange.com/a/26506
However, that might be a bit overwhelming if you just want to get a simple game going. Does your game loop happen in fixed interval or is it dependent on the framerate? Maybe you could solve a part of your issue by simply dividing the collision detection into more steps. Instead of moving the full way during one update, you could make 10 little updates that each move you only a 10th of the distance. Then you do a collision check after each step, so it's less likely that you stop too early or move through thin objects.
That would of course be more taxing on the performance, but it's a naive and easy to implement approach to a solution.
EDIT:
Just wrap the position update in a for loop. I don't know how your code for collision checking and updating, but the general structure would be something like
for (int i = 0; i < 10; i++) {
newPosX += deltaX * 0.1; // 1/10th of the usual update
newPosY += deltaY * 0.1; // 1/10th of the usual update
if (checkCollision(newPosX, newPosY))
{
posX = newPosX;
posY = newPosY;
}
else
{
break; // We hit something, no more mini-updates necessary.
}
}
Related
I am developing a game. When my main character intersects with a star(point), I should get 1 point.
I used Intersector.overlaps but when both are intersected, score is increasing continuosly until they don't touch each other. How can i fix it? I initialized int score = 0, and here my collision code,
(starAvailable = I am removing star from screen after collision. Not an important thing for scoring.)
if (Intersector.overlaps(charCircle,starCircles1[i])) {
starAvailable1=false;
score++;
}
For example, when i intersect with a star, score is becoming like this
(starAvailable = I am removing star from screen after collision. Not an important thing for scoring.)
It is actually important. The easiest and most efficient way you have to do this is to remove (or move away out of the visible field, disable... whatever you are doing to save memory) the star straight before or after changing the score, so make sure you will not trigger further collisions. There is not enough code to know how to do it in your project, but something like...
if (Intersector.overlaps(charCircle,starCircles1[i])) {
//starAvailable1=false;
removeStarFromField(); // we disable the collider, stop rendering,
// or remove the star
score++;
}
As a less effective alternative, but which may be more accessible if you have not a lot of experiece with LibGdx, and if your star has some sort of unique identifier or you can add it to it, is you could store which stars you collided with (or if you already collided with one specific star, if you are caching them). Once you collide with the star, you cache that identifier. You then should check the id fromt he star you hit against your cache, and if it's there, you shouldn't increase the score, something akin to:
// somewhere else...
Set<String> identifiersFromAlreadyHitStars = new HashSet<>();
....
// then your actual collision detection method
if (Intersector.overlaps(charCircle,starCircles1[i])) {
if(!identifiersFromAlreadyHitStars.contains(hitStar.identifier){
score++;
identifiersFromAlreadyHitStars.add(hitStar.identifier)
}
}
I solved it by adding starCircles[i].setX(1500).
if (Intersector.overlaps(charCircle,starCircles1[i])) {
starAvailable1=false;
starCircles1[i].setX(1500);
score++;
}
Stars are coming continuosly and updated in each loop, so circle's setX value is updating again after looping.
Now score is increasing by 1 for each star collision.
I am creating a Java desktop 2D Game using LibGDX.
I need to be able to move objects (controlled by the player with W/A/S/D).
The movement speed is always the same (read out from a field of the moving object).
While they are moving, they should still be affected by physics.
This means that when moving away from a magnet would make you move slower, moving towards it makes you faster and moving past it would cause you to move a curve. (see blue part of image)
Also a single impulse in while moving would knock you away but you keep moving (see red part of image)
You should also be able to change direction or stop, only stopping your own movement, so you will still be affected by physics.
So I need to apply constant forces that will still be accessible (and removable) after the next step.
Can I do this with Box2D?
-If yes, how?
-If no, any other libraries that can do this? I don't really need density and stuff like that, the use cases in the image is pretty much all I need (+ Collision Detection).
*A magnet would be a body constantly pulling other bodies in a certain range to itself
*Kockback would just be a simple impulse or the collision of a projectile with the object.
EDIT: If you know The Binding of Isaac, thats the kinda physics I'm aiming for.
Set the distance where the magnet has his influence:
float magnetRadius = 30;
Set the attractive force of the magnet:
float magnetForce = 400;
Get the position of the player and of the magnet:
Vector2 magnetPos = magnet.getWorldCenter();
Vector2 playerPos = player.getWorldCenter();
Now calculate the distance between the player and the magnet:
Vector2 magnetDist = new Vector2((playerPos.x - magnetPos.x), (playerPos.y - magnetPos.y));
float distance = (float) Math.sqrt((magnetPos.x) * (magnetPos.x) + (magnetPos.y) * (magnetPos.y));
Then, if the player is inside the magnet's radius, you must apply a force to him that depends on the distance of the player from the magnet:
if (distance <= magnetRadius) {
float vecSum = Math.abs(magnetDist.x)+Math.abs(magnetDist.y);
Vector2 force = new Vector2((magnetForce*magnetDist.x * ((1/vecSum)*magnetRadius/distance)), (magnetForce*magnetDist.y * ((1/vecSum)*planetRadius/distance)));
player.applyForceToCenter(force, true);
}
I am making a game, and I got the player to move, but when the player turns at a diagonal (Up, then up-right, for example), it's not as smooth as I want it to be.
Here's a picture showing the issue:
The player lines indicate the player's path.
How can I achieve this effect?
I'm thinking of maybe generating a bezier curve for the player to follow, but I don't know how I would get the player to follow it.
You are correct in your assumption of using a bezier curve. I would suggest (if you don't have it already) writing an Update method which you use to control the player movement on a frame-by-frame basis. In other words; a method which runs in a separate thread and triggers position updates for the player you want to move along the curve. It would act as a queue, only executing movements etc when a given amount of time has elapsed.
As for how to get the player to move along the curve, I would calculate multiple points along the curve, let's say 25 per curve. Have each point, point to the next point. These will act like waypoints - the player is given the instruction to move to the next waypoint over a short amount of time. So if you wanted to move your player along the whole curve within 5 seconds, the player would need to 'jump' from one waypoint to another every 0.2 seconds.
If you wanted the movement to be less 'jerking', you would need to write linear interpolation which would in effect further calculate smaller divisions of waypoints between each of the curve waypoints.
You can find many helpful methods for the items described above, here
In the image below, the blue blobs are waypoints.
Alternative (Simpler) Curve Approach
An alternative approach to using a bezier curve is to do a very simple smooth curve: In the case of turning right; start off with two values- Xfactor = 0, and Yfactor = 10. For this example, I assume that the speed of movement around the curve is 10 units (it could be pixels for example). For each frame, you add Xfactor and Yfactor to the players current position. You also subtract a constant (let's say 0.5 units) from the Yfactor and add it to the Xfactor. You keep going until the Xfactor equals 10 and Yfactor equals 0. This should cause the player to 'move' through 90 degrees. In order to get the player to move through 45 degrees, you would keep going until the Xfactor equals 5, as this would be half of 10. To keep the player moving in that direction, you would need to keep adding the Xfactor and Yfactor to the player position on each frame/update. Again, to make the player turn, you change the Xfactor and Yfactor over time.
I'm trying to create a simple infinite runner game. I am using Box2D for physics. When I play the game, I can see the blocks (things you are jumping on) shuttering / moving really fast from side to side (dunno if that's the word I should use). It is like there is something wrong with delta.
My game's logic:
Array of blocks - static bodies, I have always 10 blocks on the scene (if you can't see it, remove it, spawn new one, etc)
Player - dynamic body - jumping on the blocks
Camera - following player
My world has got vertical gravity (makes player fall down). I move the player by updating his linear velocity
Vector2 velocity = body.getLinearVelocity();
body.setLinearVelocity(5, velocity.y);
Drawing him this way:
batch.draw(texture, body.getPosition().x - 0.5f + delta, body.getPosition().y - 0.5f + delta, 1, 1);
As you can see, I tried to add delta to the drawing, but that didn't change anything. I draw my blocks the same way.
When I change the physics update time to 60 times per second (same as FPS), game runs much more smoothly, but I can still see that strange effect (my eyes hurt after playing it!).
Do you have any idea what can cause it? If you need anything else, I can add it.
I got some difficulties because i dont know how to code efficient.
I'm creating a vertical scrolling shooter & i wanna spawn a large number of enemies.
At certain y-coordinates of the map & give them a certain x coordinate.
If been doing testing this with a couple of enemies and in my Enemy-class the code i'm using now looks like this:
if (Background.bgY == -3972 && active == 0) {
active = 1;
type = 1;
centerX = enemyXstart4;
KnightmareGame.activated = 1;
KnightmareGame.activatedatY = Background.bgY;
}
Which basically looks for if the scrolled background is at coordinate Y, activate an enemy(bomb) of type 1 and give it starting coordinate centerX, activatedatY.
This means that for every single enemy im writing this block of code...
Then in my KnightmareGame Class (which holds the routine where the enemies get drawn on screen) i'm drawing every enemy manually, which looks osmething like this:
g.drawImage(currentBomb, bo1.getCenterX(), bo1.getCenterY(), this);
g.drawImage(currentBomb, bo2.getCenterX(), bo2.getCenterY(), this);
g.drawImage(currentBomb, bo3.getCenterX(), bo3.getCenterY(), this);
And in my collision detection method Im also checking every enemy 1 by 1:
if (projectileRect.intersects(KnightmareGame.bo1.bombRectangle)) {
visible = false;
if (KnightmareGame.bo1.health > 0) {
KnightmareGame.bo1.health -= 1;
}
if (KnightmareGame.bo1.health == 0) {
Enemy.animateFire= true;
etc., etc.
The problem is that the total amount of enemiess i exceeds 50, so if i would continue coding them 1 by 1 the code would get real messy.
What i was thinking of was that I might make an array list of all the y coordinates where i wanna spawn enemies with their subsequent x coordinate.
For example at -3900 i wanna spawn an enemy at x coordinate 200. At -3800 at x coordinate 300, etc. So an array list where every position holds 2 variables (x,y)
I just dont know (first of all) how to code for this array list.
And second. I have got no clue of how to automate my draw method like
g.drawImage(currentBomb, bo1.getCenterX(), bo1.getCenterY(), this);
I'm thinking of a loop, but dont know how the code...
Collision detection: here i also collision detect in ONE block of code for every enemy instead of compare every enemy in a single seperate block of code with my projectile.
Does any1 know how to do this? Or maybe if I should do it differently then what i'm thinking of right now?
Help will be very much appreciated!
Handling multiple enemies
Create an ArrayList<Enemy> enemies;
Then use
for (Enemy bo : enemies) {
// logic for each enemy.
}
Don't forget to remove old enemies after destroying or going out of screen.
Don't keep creating new objects every time. Use a object pool for efficiency.
Improving collision efficiency
For large number of entities to be checked for collision, generally a broadphase algorithm is used.
See if it is required in your case.
You might also try some spatial optimizations like quad-trees.
These might just be wiki links, but I suppose you can search further if you know what to search for.
Hope this helps.
Good luck.