Ok so I have a ArrayList which contains all the tiles that need to be drawn to the screen and I have the player that is moved with the arrow keys, but I am unsure how I could implement collision detection with this, Would it be efficient to check if the current tile is filled and if so stop, This is my first time creating a game from scratch so any help is greatly appreciated!
EDIT:
The tiles are 32x32 images which are held in a ArrayList basically if you guys can help me with the y-axis collision i should be fine with the rest.
Tile class contains x, y, and the tile type
EDIT2:I havent tried anything yet, I don't really know where to start but basically i need some sort of Collision on tile, e.g While player is moving if collide on tile do something but i dont know how to check if i have collided or not
Below I have an example of a bouncing ball, which will test for the end of the JPanel, and do something
//x = X-Axis Location //This tests for a collision of the JPanel on the left side or the right side
public boolean isLeavingSideToSide(JPanel jp)
{
if( x <=0 || x+ width >= jp.getWidth())
{
BounceEvent be = new BounceEvent(this);
notifyListeners(be);
return true;
}
else
return false;
}
BounceEvent is created to allow for the notifyListener, which calls the bounced method.
public void notifyListeners(BounceEvent be)
{
for(BounceListener bl : listeners)
{
bl.bounced(be);
}
}
My Bounced method changes the color of the ball (Does some action)
public void bounced(BounceEvent be) {
Ball b = be.getBall();
Color c = b.getColor();
int x = 256;
int newColor1 = (int) (Math.random() * x);
int newColor2 = (int) (Math.random() * x);
int newColor3 = (int) (Math.random() * x);
b.setColor(new Color(newColor1,newColor2,newColor3));
}
Hopefully this will help you get started.
Collision detection isn't matter for beginners, nor can it be fully explained in a Stackoverflow post; if you're still struggling with arrays, try to make simple games, where collision is detected by calculating the distance between objects like circles.
There are many ways to handle collision detection, but you have to be more specific:
what kind of tile-based game are you planning to develop?
I strongly suggest you to read this article, by Katy Coe, which gives a summary of a few implementations. The following methods are explained in the aforementioned blog.
The simplest and most intuitive method is the Pixel Colour Approach, where players can move on tiles with a specific color value, but it can be used only with a limited color palette. The Mask Approach is essentially the same as PCA, but it hides black and white layers behind custom graphics; the latter is computationally expensive and not generally recommended.
The Grid-Based Approach is probably what you're looking for. Each element of the map corresponds to a tile of the grid (described by a 2D array). The player moves in a discrete space, although animation might fake fluid movements.
The Pixel Tile Method describes collisions by sorrounding characters with n control points; this approach let the developer use non-squared characters in a tiled world.
The Bounding Box Method is a simpler implementation of PTM, where the player is wrapped in a rectangle. The program checks whether any of the four corners of the rectangle intersect with any wall.
Discrete Collision Detection, or its improved version, Speculative Contacts, are used in more complex games and you surely don't need those now.
Don't try to learn all at once, start with the simplest implementation you can think of.
Otherwise, you would soon get discouraged and would not appreciate the pro/cons of each technique.
I've recently found this great tutorial about tile-based games with Macromedia Flash, but you can easily apply those techniques using your language of choice. READ IT!
If you want an alternative to Katy's articles, Rodrigo Monteiro comes in help.
Related
In a game I am creating with slick2d to learn Java, I have multiple levels each with one Footballer and multiple other units I want the footballer to be able to interact with. I also want the other units to interact with each other (for example multiple Balls colliding with eachother) (note, some of these units are sometimes of the same class as one another e/g multiple Defenders). I am unsure, however how to detect these interactions and update the units appropriately. For example, I have my Footballer:
public class Footballer extends Unit {
public Footballer(float x, float y){
super("res/ballerpicture", x, y)
}
}
And within this class I have an update function which overrides the update function in the Unit class (allowing me to move the one Footballer according to my input - this is working without issue other than collision detection).
I could then, for example, have loaded on my map 5 balls:
public class Ball extends Unit {
public Ball(float x, float y){
super("res/ballpicture", x, y)
}
}
For an example, I would like to know how to update any one of the balls upon collision with the Footballer, moving them one tile away from the player each time they collide.
My Unit class includes a move method which moves the unit based on an integer direction (left = 1, right = 2 etc...).
Apologies if I have oversaturated this question or haven't included enough information - I'm relatively new to java.
What you are looking for is collision detection.
All objects which are able to interact with each other can have a hitbox, that's in the easiest way one geometrical shape which represents the body of an object. We could for example assume that your ball has a circle as hitbox with the radius of 8 px and your footballer has a hitbox of a rectangle with width 32 px and height 32 px.
When both objects are now moving you have to check whether the boundaries of your hitbox are intersecting with each other, if so: do something, if not keep moving.
In Slick2D all shapes have a method called intersects(Shape s), it returns true if the boundaries of two shapes are intersecting. So basically you just have to implement hitboxes for your objects (make sure to update the hitbox when your object is moving) and then check for intersecting. There are a lot of different ways of implementing collision detection and the internet is providing a lot of ressourcing regarding that topic. I also recommend to take a look at the Shape documentation of Slick2D. It's hard to write a solution for you since I don't know your code but I'm sure you will figure it out and Slick2D provides an easy preimplemented solution for your problem with the intersecting method.
It could look somewhat like the following:
Edit, for multiple balls:
//in your update method
for(Ball ball : allBalls){
if(footballer.getHitbox().intersects(ball.getHitbox()){
//get direction of footballer
ball.move(...)
}
}
In Java, I'm writing a mobile app for Android to interact with some dynamic balls with some classes I wrote myself. Gravity is determined on the tilt of the phone.
I noticed when I have a bunch of balls bunched up in a corner that some of them will begin to jitter, or sometimes slide while colliding with other balls. Could this be because I'm executing steps in the wrong order?
Right now I have a single loop going through each ball to:
Sim an iteration
Check collisions with other balls
Check collisions against scene bounds
I should add that I have friction with the bounds and when a ball to ball collision occurs, just to lose energy.
Here's a portion of code of how collision is being handled:
// Sim an iteration
for (Ball ball : balls) {
ball.gravity.set(gravity.x, gravity.y);
if (ball.active) {
ball.sim();
// Collide against other balls
for (Ball otherBall : balls) {
if (ball != otherBall) {
double dist = ball.pos.distance(otherBall.pos);
boolean isColliding = dist < ball.radius + otherBall.radius;
if (isColliding) {
// Offset so they aren't touching anymore
MVector dif = otherBall.pos.copy();
dif.sub(ball.pos);
dif.normalize();
double difValue = dist - (ball.radius + otherBall.radius);
dif.mult(difValue);
ball.pos.add(dif);
// Change this velocity
double mag = ball.vel.mag();
MVector newVel = ball.pos.copy();
newVel.sub(otherBall.pos);
newVel.normalize();
newVel.mult(mag * 0.9);
ball.vel = newVel;
// Change other velocity
double otherMag = otherBall.vel.mag();
MVector newOtherVel = otherBall.pos.copy();
newOtherVel.sub(ball.pos);
newOtherVel.normalize();
newOtherVel.mult(otherMag * 0.9);
otherBall.vel = newOtherVel;
}
}
}
}
}
If this is the only code that checks for interactions between balls, then the problem seems pretty clear. There is no way for a ball to rest atop another ball, in equilibrium.
Let's say that you have one ball directly on top of another. When you compute the acceleration of the top ball due to gravity, you should also be doing a collision check like the one you posted, except this time checking for dist <= ball.radius + otherBall.radius. If this is the case, then you should assume a normal force between the balls equal to that of gravity, and negate the component of gravity in line with the vector connecting the two balls' centers. If you fail to do this, then the top ball will accelerate into the bottom one, triggering the collision code you posted, and you'll get the jitters.
Similar logic must be used when a ball is in contact with a scene bound.
Since I've been experimenting with my own Phys2D engine (just for fun), I know you're talking about. (Just in case - you may check my demo here: http://gwt-dynamic-host.appspot.com/ - select "Circle Collisions Demo" there, and corresponding code here: https://github.com/domax/gwt-dynamic-plugins/tree/master/gwt-dynamic-main/gwt-dynamic-module-bar).
The problem is in a nature of iterations and infinite loop of colliding consequences. When e.g. ball is reached the scene corner, it experiences at least 3 vectors of force: impulse of bounce from the wall, impulse of bounce from the floor and impulse of gravity - after you summarize all 3 impulses, reduce it according loosing energy algorithm, you have to have the new vector where your ball should be. But, e.g. this impulse directs it into wall - then you have to recompute the set of vectors again according to all the stuff: energy of bounce, impulses, gravity, etc. Even in case if all these impulses are small, you never get all of them 0, because of precision of doubles and your tolerance comparison constants - that because you have the "jitter" and "sliding" effects.
Actually, most of existing 2D engines have these effects one kind or another: you may see them here: http://brm.io/matter-js/demo/#wreckingBall or here: http://box2d-js.sourceforge.net/index2.html - they actually just make the small impulses to be absorbed faster and stop iterating when the whole system becomes more or less stable, but it is not always possible.
Anyway, I'd just recommend do not reinvent your own wheel unless it is just for your fun - or for your better understanding this stuff.
For last one (JFF) - here is good tutorial: http://gamedevelopment.tutsplus.com/tutorials/how-to-create-a-custom-2d-physics-engine-the-basics-and-impulse-resolution--gamedev-6331
For real things, I'd recommend to use the existing engines, e.g. Unity (https://unity3d.com/learn/tutorials/modules/beginner/2d/physics2d) or Box2d (http://box2d.org/)
Hope this helps.
Iterating through all the balls and changing the balls position for each iteration is probably the cause for the instability, you move a ball left to avoid collision on the right, and then you pushed the ball into another ball on the left, and then the left ball tries to push it back again.
From the top of my head I could recommend trying to sum up all the forces on each ball before doing anything about positioning. And if you iterate from the ball "on top" (furthest away from gravity source/direction) you can probably achieve a stable situation.
Basically, the top ball needs to first calculate forces between itself and the ball(s) under it, plus gravity, then the ball under will know how much force is coming from the top ball, and added with gravity it would also add to the force of which it is pushing the balls under it. When all balls know the forces they're pushed with you can transform that force into motion.
The way you are simulating the physics of the balls is bound to cause instabilities. Your collision resolution tries to separate the balls by projecting one of them in the opposite direction by the collision depth. This may fix the overlap for those two balls but chances are(especially when the balls are stacked) that the ball is now overlapping with another ball.
There are many ways to fix penetration. One of the simplest ways is to add a "bias" or a bit of a push to both bodies to force them to separate over the next couple of frames. This allows that energy to propagate and force all of the bodies apart. Problem is, the bias will often overestimate and cause a bit of a bounce. To fix that problem I'd recommend reading up on sequential impulse.
Making physics look realistic is not as easy as it may seem. Unless you don't mind instabilities I'd recommend spending some time reading up on different techniques or using an engine such as Box2D.
I am working on a simple 2D game with Java, swing and no framework. I have a rectangular player that the user can move around. On the map are few obstacles which the player should not be able to go through. I did this by making a new Rectangle Object for the player and each obstacle with their bounds. But I’m not really sure if this is the right way to do it. It works but the movements of the player are not really user friendly. If the player wants to pass two obstacles they must be on the perfect coordinates to pass.
Is it even a good idea to check for intersections between the player and the obstacle with a Rectangle object or should I do it another way?
Now for my 2nd question:
I’d like to replace the rectangular hitboxes with the same hitbox but with rounded corners so the player could pass more easily.
This is what the game looks like with hitboxes enabled.
The code that checks if the player and the obstacles have yet intersected:
for (Player p : this.getPlayerArray()) {
Rectangle recPlayer = p.playerBounds();
for (Obstacle kiste : obstacleArray) {
Rectangle recKiste = kiste.obstBounds();
if (recPlayer.intersects(recKiste)) {
p.setX(100); //Not actual code here
}
}
}
The function that returns the hitbox of the player / obstacle:
public Rectangle obstBounds() {
return new Rectangle(this.getX(),
this.getY(), image.getImage().getWidth(null),
image.getImage().getHeight(null));
}
Many years ago I wrote a Khepera simulator as part of my undergrads' final year project. I started by doing collision detection as you are doing, that is intersecting areas... My supervisor made me notice that since the shape of my robot was a circle I just could check if the center of the robot was inside another shape, if that was the case a collision occured.
Your case is even simpler since you move on tiles... so either you do (as suggested in the comments) maintain a set of "move/no move" tiles and check that, or you just check that the position of your player is within, or not, a 'forbidden' rectangle, i.e. an obstacle. If it is, then you have to reset the position of the character to be 'outside' of the obstacle (minus the character's bounding box, obviously)
I strongly suggest to do it the tiles way: allow only up/down/left/right movements and check against a 'forbidden' set of movements given a tile-position. If you really want 'freedom' of movements than go with circles (bounding boxes/circles) because they are easy to reason with, easy to do a position reset (in case of collisions) and perfect for your case (every tile can contain a circle, whether an obstacle or the player.)
There are many ways to go about collision checking, but I think a simple approach would do just fine for your use-case.
First from the looks of your screenshot, a tile is either an obstacle or passable, but never half of each. In that case it would be simplest to just check on which tile the center (or feet, choose what looks best) of the character are.
If its an obstacle, they cant go there, simple as that. Note that this will allow the player to move partially into an obstacle, but many games do it this way and players are certainly used to this behavior, especially in 2D games with graphics designed to look like an isometric projection (which I would yours class as). A variation of this would be to simply make the player collision rectangle smaller (say half a tile, again centered at the player sprites chest or feet).
I am coding a game using LibGdx and I have an array with all of my wall objects that the player can collide with. For those who don't use LibGdx, I am talking about LibGdx's Array class which provides the same functionality as an ArrayList but it's built with memory efficiency in mind. When I check for collision, I am having to go through every wall in the array and check for collision like this:
for(Wall w : walls) {
if(w.bounds().contains(player.bounds()) {
// handle collision
}
}
I realized this was inefficient because I am going through every wall even if that wall is off the current view of the map. Obviously, if I am checking for collision with walls currently in the camera's viewport (this means they are currently visible by the player) then there is no point in going through the whole array because the player can't collide with them until they come into view. I was thinking of making my game a bit more efficient by only checking for collision with walls close to the player. In my game, I have all of the walls snapped onto a grid with cells 32x32 px. I really don't know how I could create more efficient searching for collision. Could I use like a map of some sort which uses a vector2 position for its key and then look up the player's position and look through walls within a certain range from the player's position in the map? I am just really lost on how to have code that won't go through all 100+ walls in my game when there are only 10 current possible walls that the player could touch because of where it currently is. Does this make any sense? Could someone explain a good way to do something like this? Thanks so much.
There are lots of collision alghoritms out there, you will need to find one that suits your need.
One solution I can think of on the top of my head is:
Keep your wall list sorted on their coordinates. If you create a new wall, use insertion sort to resort your array. When you want to check for collisions, take the objects coordinates (in this case probably the player that is running) and do a binary search to find the closest wall to the player. Then calculate if the player and this wall collides. If the closest wall isn't causing a collision, you can be pretty confident that no other wall is as well.
Each wall is on one or more of these 32x32px grids. Let the coordinates of a grid be x and y. If a grid contains a wall, enter this into a
HashMap<CoordPair,Set<Wall>> xy2wall
To investigate where a location is in contact with a nearby wall, use the coordinates of the location to determine a small set of grid coordinates, fetch the set or sets of Walls mapped by these CoordPairs. I guess the Player.bounds() can provide a suitable set of coordinates.
If the 32x32 grid results in too many entries, you can always use a coarser grid.
I once came into the same realization that you have while developing a top down rpg.
There are more walls than you can imagine in a top down rpg.
Here is how I solved it:
First: Segment the map into zones ie.) draw your map on paper or something and cut it up into parts.
Second: Record the pixel boundaries for each segmented section of the map.
Third: Check where your players location is with respect to the boundaries.
Finally: Only check the walls within those boundaries.
In a realm of infinite walls this is not any more efficient (speaking about Big O) but for all practical purposes this is effective in cutting down on lookup times
if (boundary1.contains(player1)) {
for(Wall w : Boundary1Walls) {
if(w.bounds().contains(player.bounds()) {
// handle collision
}
}
}
else if (boundary2.contains(player1)) {
for (Wall w : Boundary2Walls) {
if(w.bounds().contains(player.bounds()) {
// handle collision
}
}
}
....
Continue in this fashion
Take note... I did it like this before going to college for software development, so I did not make use of data structures such as BST which could be used to store walls with respect to their coordinates. Making your lookup time extremely fast.
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! :)