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(...)
}
}
Related
I developed a 2d game in android studio using SurfaceView,
it's not complex in context of collision, just need to check collision between a moving-point and some static circles, for detect collision for one circle, I simply check if X of the point is between circle minX and maxX && point Y is between minY and maxY of circle.
So for checking collision in whole of the game, I repeat to check above code for all circles in each frame.
Game work so good when I have for example 10 circles, but if I add 30 circles, its FPS decrease so much and I face so much lag!
What should I do for this problem? should I use Box 2d physics ? what does it do for collision detection that games doesn't face lag problem even if there is so much objects which collide together?
Please help me with more detail, because I was wonder how a game engine work and decided to make a simple one, not only wanted to make and release a game(otherwise I could use a ready game engine).
Thanks in advance
As for how game engines do it, it is probably easiest to look at their source code directly, as at least one version of Unity can do it - you can find the source code of Unity here.
In your case, you could potentially trade off increased memory consumption by your app to make collision detections essentially constant-time regardless of the number of circles, as suggested by #SagarGautam in his comment.
What you can do to achieve this is store a 2D array of booleans indicating all map pixels, setting each element to true if it is inside a circle (as per your previous code) or false otherwise. Doing this during the loading phase of the level/map should be fine, because now during rendering you can just look up the pixel coordinates in the array and see if it is inside a circle or not.
In 3d game i use Colliders so check if there is any collider(mesh,box,etc.)
give tag to that objects.and identify them by tag
Example:
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour {
void OnCollisionEnter2D(Collision2D coll) {
if (coll.gameObject.tag == "Enemy")
coll.gameObject.SendMessage("collided", 10);
}
}
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'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 looking at making pong using LWJGL.
Well I was doing the LWJGL tutorials, by thebennybox, and had it working, I then wrote it out again when my old hard drive died (R.I.P). What I am trying to do is add multiple GameObjects and have them show up, I worked out that they are being added to the GameObject objects list. Here is the code in my dropbox: https://www.dropbox.com/s/ccs37jqm1b5oi84/lwjglGame.zip
It is a little too big to have on here but here is a main part:
This is from Game.java:
private ArrayList<GameObject> objects;
public Game() {
objects = new ArrayList<GameObject>();
GOplayer player = new GOplayer(0, Display.getDisplayMode().getHeight()/2);
GOball ball = new GOball(Display.getDisplayMode().getWidth()/2-GOball.SIZE-2, Display.getDisplayMode().getHeight()/2);
objects.add(player);
objects.add(ball);
}
Your problem occur because of two problems.
1: Within the GameObject class your float variables x and y are static. Which they should not be!
2: Within the Draw class you call glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); this should not be there as well, because what that does is clearing the depth and color buffer, which results in each time your render a "rect" using you Draw.rect that clears the screen, so in the end, only the last rendered "rect" will be shown!
Also you don't really need to clear the GL_DEPTH_BUFFER_BIT, since within the initGL() you disable it using glDisable(GL_DEPTH_TEST); (though GL_DEPTH_TEST is disabled by default). And since your only working in 2D space then there are no actual depth, unless you're using the GL_DEPTH_TEST to sort the 2D space, while still using Z values.
Advice
Here is just some advice from me, if you don't 100% know all the main/basic keywords within Java, or just don't know how to use them correctly then starting off by creating a Game with OpenGL using LWJGL, will become extremly hard for you at some point. I suggest you start with something a lot easier or start off by reading or watching multiple tutorials about the basics of Java.
The reason I'm saying this is that you create a new instance of the class GameObject through GOball, GOplayer and GObox though inside the GameObject you have the float variables x and y those variables you've set as static, which mean that variables are shared and will always be the same. So when you create an GOball and set the x and y that sets the x and y though when you then create the GOplayer and set it's x and y to something else, that will affect the GOball as well so then they will have equally the same x and y always, since the variables are shared!
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.