Collision Detection - How to Make a 2D Game in Java #6
Vložit
- čas přidán 2. 06. 2024
- In this video, we will implement collision detection so player character stops when he tries to walk through solid tiles.
Caution: This is a tutorial for Java 2D beginners so it's pretty verbose! (and the pacing is a bit slow...)
If you want to use my assets (images/maps/sound) that are used in this tutorial, here's the link:
drive.google.com/drive/folder...
Guidelines for using Blue Boy Adventure's code and assets:
docs.google.com/document/d/1q...
If you have any questions, feel free to leave a comment.
Thanks for watching.
Timestamps:
0:00 Set tile collision status
1:54 Set player's solid area
7:28 Set up Collision Checker
10:28 Detect collision
25:40 Final result
#javagamedevelopment #java2D #javagametutorial #javagameprogramming
what the hell, dude being haunted in 1:09 and kept recording, absolute legend.
best Programming series on youtube
I can't wait to jump in on this guide as I've tried to understand how collision was detected for a while. Your guide is the only one I understand!
Thank you so much, I really enjoy these videos they're so helpful, you deserve so much more views!
Man, you're a legend, thank you for your tutorials! 👍
Glad you like them! Thank you for the comment.
Thank you, RyiSnow, this is a wonderful series. Learning a lot!
A small addition: If you still want to be able to change the scale factor one should base the collision rectangle coordinates on the 16x16 image (not the 48x48) and multiply it by the scale factor upon initializing it in the player class.
Yess glad someone pointed it out. Those fixed numbers looked out of place to me lol
With great help of your videos I might be able to make a tile based strategy, and then a 3D version of it, and not only it. Thanks for the help 🙂😌
hope this tutorial series never ends
Also thanks for making this series, i needed it so much!
your videos are indeed very clear and helpful
Another great video, these are so helpful and really appreciated, thanks so much!
You're welcome! Glad I could help :)
really nice tutorial, thanks a lot ! you deserve way more views !
Thanks for the video, I was confused on how to implement a Collision Detection
Was waiting eagerly for this video Thanks :)
Great video! I just want to mention since theres a few people in the comments who ran in the same issue, there is an issue when "solidArea.x" is made equal to a ratio of the "tileSize" if you want to maintain the "scale" functionality because it is integer division and the compiler will round it up or down to unpredictable number and the collision detection will work very strangely as the collision box will not be where you expect it. The solution is to use hardcoded numbers like in the video, or make the tileSize a "double" and not "int", but this would require everything else that tileSize interacts with to be recast to double instead of int. I'm guessing this is why you used numbers in the video instead of tileSize.
For anyone who may run into the same problem I was, where despite my code being the same as what is in the video, my player character wouldn't move, make sure that you have '==' in your if statements and not a singular '='. I was overlooking this because it's such a small detail, but it was making the body of my if statements unreachable and preventing movement. After changing this, my character was able to move.
When I do that, I'm getting an error reading "Not a statement". How do I fix that?
Its makes huge difference. In programming == typically means to check if a certain value is equal to another, typically used in if statement, while a single = just assign the value so yeah it literally changes meaning so of course it will not work. It's not what i would call small detail haha
If your character get stuck on collisions sometimes, check if changed the - to a + in case "down" and case "right" in the CollisionChecker.
you're the goat thanks :P
Thank you too.
tysm
Thank you so much for these tutorials
Man Loved This tutorial. You're legend
Cool video tutorial! The result of this video makes me happy
Great Tutorial as always
This is a great great great work... big salute to you bro...
I've been waiting for your new video for 1 week
Hope you make more videos in the future
I have a full time job so can't promise but hopefully I can spend more time for making videos this month.
I can't thank you enough for these!!
Thanks you so much for this video!
you are a man of honor
Thanks a lot for these videos!
i love your videos very much
Glad to hear that!
Loved the vid! I was wondering if you would incorporate random terrain generation in your game?
Not in this one. This is for 2D game beginners and I'm trying to keep it simple so the code is not overwhelmingly complicated (You'll need to construct an algorithm to do random generation). Maybe I will do in the future though.
@@RyiSnow Ok, thank you for replying!
I have an idea for this based off my knowledge and how games like Minecraft are loaded. I'll see what I can come up with!
For something simple could use a markov process where tile probability is based on tiles neighbors. This would generate clusters like forests, oceans (w/ sand) or other things depending on those probability values. Tweak and have fun:)
Thank you so much for your videos.
do you know if there would be a way to do this but keep the ability to move the player diagonal like you could before there was any actual collision detection
super video as always
Hi Ryi, not sure if you're still reading the comments on your old videos, but there's a problem with collision rectangle object size not being dependent on scale. If you change the scale variable, the collision rectangle will still have the x, y, width and height as if the tileSize was 48. It can be fixed with multiplying rectangle arguments by scale. However, when I tested that, I also noticed that player moves faster on lower resolutions, and slower at higher. Is it intended, or addressed in later videos?
What do you mean by that? I’m currently building the game but I’m having issues with the collision. My characters width and height that I want for collision is 13 x 13. It is 9 pixels from the left border and 19 pixels away from the top border. However the issue is I’m still colliding with the actual tile size of 48 x 48 if I get to close to a tree for example.
Thanks so much, very helpful. Any ideas on how I would change the player and collision checker class if I wanted to implement gravity? I used the same tile method for collision and my sprites are in 2D, however I’m not sure how to add gravity and jumping.
Enjoyed it!
daaaamn thaanks i was waiting for it haha
Nice brA, you are deserved to be BIG THREE ecole
For anyone who finds their player character gets stuck, make sure that you have a ‘break’ in each switch statement for the collision checking. Otherwise all 4 collision checks are done for each movement and you’ll get stuck.
God bless you your videos helped me so much thank you thank you
Thank You so much RyiSow
Hi RyiSnow, I'm loving your content! I am currently up to episode 14 of the series, as I just found this amazing channel, except I have ignored a problem on how if I switch keys really fast next to an object, I can noclip through it, the NPC also knows how to do it! Can you please help me? Also, if I am not on the center of an object, but a bit lower, I can move through the object, as if the tree is a pixel small.
Hi RyoSnow, I don't know what happened but when I remove the code "worldY -= speed" from update(); and I put it in if(collisionOn == false){ switch(direction){}}, my player is extremely slow, but when I return to the previous location it returns to normal.
Soo I have a problem, whenever I colode with an tree up down or left I can use the opposite direction to move away. If I collide with something on my right side the only way I can get out of colliding is if I go up or down , when I press left the animation plays but I don't go anywhere. PLEASE HELP! all help/ advice is welcome.......
Good work :)
Hi Ryisnow! Really greatful for your tutorials, am wondering how would I go about making a collision checker between two player models? So far I am currently able to make that the player models can only collide with one another when one is stationary not while moving. Any help would be great!
We've handled collision between characters in Part 14 so you might want to check that video.
Thanks so much for this
Hello Ryi this is Martell. How are you? Question: This question is a bit off topic so I apologize, but I want to know....how can I make JText field transparent? I tried to set the main text area to Opaque and that doesn't work. I even tried to set the background color to 0,0,0,0 and that didn't work either. I also tried to set the panel itself to OPAQUE and that didn't work. Can it be done?
JTextField tf = new JTextField();
tf.setOpaque(false);
tf.setBorder(null);
This makes it transparent.
Great Video
Great vid and it really is helping me, but i have found several places where due to collision n the rectangular size make the player stuck in the same position Its like u cant move away from that place. Forever Stuck, was wondering, is there any solution to that?
check your collisionChecker. if you put the "break;" statements of switch's in the if statements, it happens. put it outside of if statements.
Great videos, they're helping a ton. I do have a question though. If my character collides with an object going up or down, they suddenly can't move side to side. I can't really seem to figure out what the problem is.
Nevermind I fixed it. It was because I was trying to use a double speed and so had to cast speed as an int in the collision detection class, so it was rounding the speed slightly lower than it should have, there for triggering the side to side collisions.
7:22 @RyiSnow, Why didn't you use a calculation of gp.tileSize here? It may seem like unnecessary math, but if somebody decides to change the scaling of the game, then this part of the game would not function correctly.
I've watched this video 3-4 times in the last week and I can't understand a single thing on your checkTile method hahaha... I've seen in google that the Rectangle class has a collision method, would it be possible to use that method to make it simpler? Also I read a comment of a guy asking for randon terrain generation and that would be awesome.
Greetings from Spain and thank you so much for these videos Im learning a lot! :)
Could I make method such as this?
public void createTile( int tileIndex, String filePath, boolean collision) throws IOException {
tile [ tileIndex ] = new Tile();
tile[ tileIndex ] . image = ImageIO . read (getClass() . getResourceAsStream ( filePath ) ) ;
tile [ tileIndex ] .collision = collision ;
}
Update: in checkTile function I’ve found an issue regarding collision detection make sure to add spacing between the front slash “/“ or else its considered a division (example: entityTopRow - entity.speed / gp.tileSize) this one was very difficult to find since its the exact same thing I see on the video. Hope this helps
I think you forgot to put entity entityTopWorldY - entity.speed in bracket
Like this
(entityTopWorldY - entity.speed)/gp.tileSize;
I'm having a problem with the movement, when I pressed S and then W my character won't go up same with pressing D and A. I can't pressed 2 keys at the same time. but its working on pressing W first and then S and A first and then D
is this method of detecting collision using the Separating Axis Theorem (SAT)? I've heard that it is used to detect collision in games but I don't know how to implement it and I've never seen it in plain code :S
Another great video ta, having a weird issue with this collision though, when I spawn in the game using your world01.txt if I go right or left from the spawn location I can't get through the gap in the trees unless I lower the rectangle size on my player. But it seems yours was fine, am I missing something?
Did you fix that yet, I have the same problem
same, did you find the reason?
@@hijo-0191 nah, I just made the rectangle smaller I think
@@bertrodgers2420 i fixed it, i accidentaly put = instead of + on the entity at 12:30.
Hello, I’m making a rpg game that is somewhat like a text game where they have to choose what to do. I’m wondering if it’s possible to make it if my sprite touches a certain tile it would open up a new jframe once. But it would also keep the sprite in the same position when it comes back.
You can do that. As long as you don't update the player's position while other JFrame is opened, the character stays at the same spot.
Also, make sure that you let the entity check the direction it is colliding, example:
I don't know what this:
entityRightCol = (entityRightWorldX + entity.spd) / (gp.tileSize);
was used for and even accidentally did this instead:
entityRightWorldX += entity.spd / gp.tileSize;
This part of the code actually detects the collision before the entity gets too close to the tile and detect multiple collisions. I learned this the hard way.
Hi Ryi, I got my collision working for the most part, but I've run into an issue when the bottom of the players hitbox is aligned with the bottom of the collision tiles, it will phase through it. I don't run into this issue when the left and the right of the hitbox are aligned with the left or right of the collision tile. Do you happen to know where I went wrong as yours doesn't seem to have that issue.
I'd be happy to supply the code through Github if you need context
For some reason, when I go down, it goes halfway through the tree. I even drawed a black box on the screen as the collision zone and I see that it goes right through the box. This only happens when I go down, not with any other directions. Could you tell me any common mistakes people make so I can check if I made them?
i have the same problem, did you solve it ?
I find the solution :
in the CollisionChecker for case : "down" he made the same mistake than for right so you have to replace the " - " by a " + " on the first line of case down.
why my player continues moving down even if i did not control it and when i switch to right or left if also continue moving and when up is stop
If u have the problem that u ato walk after u included the collision for the "up" statement is here the solution: Import the code (to be seen at 22:44) on top to stop it from looping. It was created a few parts ago to make the player stop moving when hes standing. Hope I can help.
Hello! Thank you for all these videos, you helped me improve the foundations of my knowledge and in some cases (like in threads) you helped me understand much better everything that at the time I couldn’t understand.
But I have a question, in some cases you divide some values by the tileSize and I don’t understand why, could you explain this better to me? The case where I have the most doubt is in the formulas you used at minute 17:00. Why did you do it like that and what does it return? THANK YOU!
We divide them by the tile size because we need to get col and row numbers instead of x and y!
@@RyiSnow for a moment, I also wondered why. but i think, to explain it better, it is because you are looking for a tile in that position, so you divided it by the tileSize.
the four (4) numbers you made are like (4) pin points, or simply (4) corners of the collision hitbox, where these pins checks whatever tile they're standing on, whenever you told them to (every frame update, in this project), so that these (4) pins can tell you if it's a solid tile or not. if it's solid, we won't let the player move further to where they want to, otherwise, we will let it happen.
to make it more clear, these (4) pins can actually detect 4 different tiles, with the help of tileSize variable, if we let it.
I've actually been having a bit of trouble when it came to player movement after moving the world speed to the if-statement: if(collisionOn == false) for the player class. For me, after making this change, the player just keeps moving in whatever direction that it is facing. The problem started at around 22:50 for reference. Any ideas that could have caused this problem?
May I see your Player class? You can paste it here.
Looking at the code again, I think I see the issue: all of the movement code is running under an if statement that checks if a key is pressed. I don't have this for some reason and found my own workaround, but you could probably just add that if statement under update() in player. Look for it on line 71 in the video, or you can see it at 22:22
Without this if statement, the only guard on applying speed to position is whether you're colliding or not, and as you usually aren't colliding at this point in the video you'll just move forever.
@@RyiSnow
package tWoD.src.Entity;
import java.awt.image.BufferedImage;
import java.awt.*;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import tWoD.*;
import tWoD.src.Entity.*;
import tWoD.src.Main.TwoDGamePanel;
import tWoD.src.Main.TwoDKeyHandler;
public class Plr extends Entity{
TwoDGamePanel gp;
TwoDKeyHandler keyH;
public final int screenX;
public final int screenY;
public Plr(TwoDGamePanel gp, TwoDKeyHandler keyH){
this.gp = gp;
this.keyH = keyH;
screenX = gp.screenWidth / 2 - (gp.tileSize / 2);
screenY = gp.screenHeight / 2 - (gp.tileSize / 2);
solidArea = new Rectangle(12, 18, 24, 30);//works by x,y,width,height
setDefaultValues();
getPlayerImage();
}
public void setDefaultValues(){
worldX = gp.tileSize * 25;
worldY = gp.tileSize * 25;
speed = 4;
direction = "down";
}
public void getPlayerImage(){
try{
left1 = ImageIO.read(getClass().getResourceAsStream("..\
sc\\Player\
obotPlayerAWalk_1.png"));
left2 = ImageIO.read(getClass().getResourceAsStream("..\
sc\\Player\
obotPlayerAWalk_2.png"));
right1 = ImageIO.read(getClass().getResourceAsStream("..\
sc\\Player\
obotPlayerDWalk_1.png"));
right2 = ImageIO.read(getClass().getResourceAsStream("..\
sc\\Player\
obotPlayerDWalk_2.png"));
down1 = ImageIO.read(getClass().getResourceAsStream("..\
sc\\Player\
obotPlayerSWalk_1.png"));
down2 = ImageIO.read(getClass().getResourceAsStream("..\
sc\\Player\
obotPlayerSWalk_2.png"));
up1 = ImageIO.read(getClass().getResourceAsStream("..\
sc\\Player\
obotPlayerWWalk_1.png"));
up2 = ImageIO.read(getClass().getResourceAsStream("..\
sc\\Player\
obotPlayerWWalk_2.png"));
}catch(IOException e){
e.printStackTrace();
}
}
public void update(){
if(keyH.upPressed == true){
direction = "up";
}
else if(keyH.downPressed == true){
direction = "down";
}
else if(keyH.leftPressed == true){
direction = "left";
}
else if(keyH.rightPressed == true){
direction = "right";
}
// CHECK TILE COLLISION
collisionOn = false;
gp.cChecker.checkTile(this);
// IF COLLISION IS FALSE, PLAYER CAN MOVE
if(collisionOn == false){
switch(direction){
case "up":
worldY -= speed;
break;
case "down":
worldY += speed;
break;
case "left":
worldX -= speed;
break;
case "right":
worldX += speed;
break;
}
}
spriteCounter++;
if(spriteCounter > 15){
if(spriteNum == 1){
spriteNum = 2;
}
else if(spriteNum == 2){
spriteNum = 1;
}
spriteCounter = 0;
}
}
public void draw(Graphics2D g2){
//g2.setColor(Color.white); // colors g2 - ismael notes
//g2.fillRect(x, y, gp.tileSize, gp.tileSize); // placeholder for player character thus making it the size of tileSize - ismael notes
BufferedImage image = null;
switch(direction){
case "up":
if(spriteNum == 1){
image = up1;
}
if(spriteNum == 2){
image = up2;
}
break;
case "down":
if(spriteNum == 1){
image = down1;
}
if(spriteNum == 2){
image = down2;
}
break;
case "left":
if(spriteNum == 1){
image = left1;
}
if(spriteNum == 2){
image = left2;
}
break;
case "right":
if(spriteNum == 1){
image = right1;
}
if(spriteNum == 2){
image = right2;
}
break;
}
g2.drawImage(image, screenX, screenY, gp.tileSize, gp.tileSize, null);
}
}
@@_chaozgt_ Just like ciTatic says, you haven't added the if statement to check key input. So the program keeps adding the speed value to player's worldX/Y. I guess you skipped a part in Part 3 video.
@@RyiSnow Oh, i see, thank you!
Hi @RyiSnow! I just wanted to ask: when I from video #2 removed the "else" parameters from update method in Player, I was able to make the player move diagonally. But after video #6 with this Collision-function implemented I wasn't able to anymore.
Do you have any way/function for implementing diagonal movement for the player, or is it unable to in the particular way these classes and program is constructed?
If you want to keep diagonally movement, here's basically what you need to do:
1. In the update(), store the current worldX and worldY in temp variables before adding/subtracting any speed values.
2. Add or subtract the speed value in the if statements where you set direction (basically keep the former method)
3. Check collision
4. If a collision happens, reset the worldX and worldY by using the stored temp values.
@@RyiSnow Hi! I must first say thank you again for your awesome videos and dedication of this. I´m learning so alot of this and its really helping me in my Java-school im going on right now, you are gold! Just so its notified and cleared :) Keep rocking on!
I just tried your code implemementation, and ended up something like this:
public void update() {
int tempWorldX = worldX;
int tempWorldY = worldY;
if(keyH.upPressed || keyH.downPressed || keyH.leftPressed || keyH.rightPressed) {
if(keyH.upPressed) {direction = "up"; worldY -= speed; }
if(keyH.downPressed) {direction = "down"; worldY += speed; }
if(keyH.leftPressed) {direction = "left"; worldX -= speed; }
if(keyH.rightPressed) {direction = "right"; worldX += speed; }
//CHECK TILE COLLISION
collisionOn = false;
gp.cChecker.checkTile(this);
//IF COLLISION IS FALSE; PLAYER CAN MOVE
if(!collisionOn) {
worldX = tempWorldX;
worldY = tempWorldY; }
And it seems like the inputs are now working, but the player just stands on the starting tile = not moving (although animation+keystrokes work) any suggestions?
I think it's a simple mistake.
Change:
if(!collisionOn)
To
if(collisionOn)
!collisionOn means it resets the character's worldX and worldY when collision is NOT happening so it's only natural that you cannot move
@@RyiSnow Man, i cannot say thank you enough.. You == legend. And i can say me as a class representative many in my class are starting to take interest in your videos here in Sweden as well, even our teachers! So you are superb. Keep having a good life, and remember to take breaks from the computer as well and allow yourself some treats and something good for yourself.
That was, however, the issue. Now that i see it, and you said it as well it became really well logical. Thank you for help!
It seems like I have some kind of issue with the collision. My CollisionChecker class is identical to yours but when I run the game, the character is stuck, frozen in place and no animation being played. When I comment out the code to check tile collision in my player class, my character moves again, but can't stop. Terminal output also mentions "java.lang.ArrayIndexOutOfBoundsException: Index 1056 out of bounds for length 50". I have no idea what causing these problems as I followed the collision detection tutorial exactly.
EDIT: I figured out at the 20:17 mark I unknowingly put the parenthesis in the wrong place (place the ")" behind ".speed" instead of "gp.tileSize", how I did that I don't know), but the character is constantly moving in one direction unless it collides with a tile...
@CrippinDoge it should be
entity.speed) / gp.tileSize;
rather than
entity.speed / gp.tileSize);
In this comment I've found salvation, thanks.
hellooo.... could I get some help please? my top collision works but the other directions are not working. I've watched a few times but still can't figure out what I did wrong :(
Edit: so for some reason my solidArea.height is not working, as a result entity bottom row wasn't either. for now I changed the solidArea.height to width for entityBottomWorldY
So I've been having an issue with the collision. The map is loaded fine, however I will run into seemingly random collision areas on the map, and sometimes where there should be collision there isn't. I have redone the collision from this video, I have looked at the line string input for the map, made sure the correct tiles have had collision on. I am unsure where to go from here.
Also what is the counter2 initializing in the player subclass?
Well, the issue(which I haven't resolved) is the world01.txt is only loading half the map but making that half take up the 50x50 allocated tile slots. The bottom half will load but not the top. if I change maxWorldX and maxWorldY to 100, the map does not load with any of the textured tiles other than the grass tiles.
@@youreawesome718 seems like problem is caused by the use of incorrect variables.
Hey Ryi, as always your videos are awesome! Because of school I had to set this down for a while but I'm back at it again! This time I want to finish it 😄
I have a question while I'm here on this video. I'm not sure if you're still taking questions, but let's say I have a 32x32 tile, and on this tile I have drawn a treasure chest that only takes up 16x32 of the tile. Is there a way that instead of using the entire TileSize as the collision I could set it in a way that each tile has it's own "temporary collision size" so to speak? I've tried implementing this myself but I can't seem to get it right.
You can use the Rectangle class for that, as we did for checking NPCs/Interactive Objects collision :)
@@RyiSnow Ah thank you so much! Let me try that and see if I can get it to work 😄
@@RyiSnow Hey so i followed everything right but when i type collisionOn ut gets an error i dotn know why tho
When i change the player.update() to implement the collision system i had a problem: when the game starts my character starts move down automaticaly. This happened because of two things:
1 - we change the way we increment the player position in the world. Before was in the if statment:
if (keyH.upPressed == true) {
direction = "up";
worldY -= speed;
}
then it was in the switch case:
switch (direction) {
case "up": worldY -= speed;
break;
2 - i did no include t[he if statment: if(keyH.upPressed || keyH.downPressed || keyH.leftPressed || keyH.rightPressed) {
// code
}
because i liked the player moving still, its like a breathing animation. But i couldn figure it out how to fix this without adding the conditional, sadly.
But its ok, let's keep going. Great video, as always
thank you very much, i had the same issue
Hey really great tutorials i like it a lot, but i have a problem i implemented diagonal movement to my game but now its not working any idea how can i fix it?
Late reply but better late than never!
Referencing to this specific tutorial, the easiest way to implement diagonal movement is to go to the update() method in Player class (where we check "which key did the Player pressed?") and make the chain of "if, else if, else if, else if" just a series of 4 if "if pressed UP, if pressed Right etc". That way code execution will "enter" more than 1 if, thus enabling diagonal movement.
Perhaps the reason yours stopped working is you made your 4 ifs into if/else if chain?
Hi, can you explain the checkTile section with numbers instead with words, or both. Thank you.
I'm trying to make pacman game using your code but the collision detection isn't working.
So when i loaded the map i created an arraylist of rectangils of all blocks on the map that holdes each block x and y. And inside CollisionChecker i have a method that takes an entity as a parameter and loops over all the rectangles arraylist and checks if the player intersects with any of them using intersects method.
So, is what i'm doing right? Cause it's not working. It's not giving any errors but the player can still walkthrough blocks.
Edit: I fixed it by updating player's solidArea's cordinates in player's update method and also figured that i didn"t calculate the speed inside collision checker and now it's working.
Now i'm trying to implement pacman movement by storing the next direction in a string and checking if the next direction's casues collision or not to decide when to change the current direction.
Edit1: Finally i've succeeded to implement pacman's movement. It took me hours because he was getting stuck when he tried to enter a tight turn but somehow it worked at the end. I also added the food and implemented food interaction and now he can eat food and store score hos score. The only thing left is adding ghosts and sounds.
hi RyiSnow, thanks for the great tutorials, but i have a problem, when i am between two tiles my character no longer moves and freezes. any solution?
I have the same issue.
@@masterdob7600 I solved it, you have to be careful at the beginning of each "case", where you find the entityTopRow variable
@@sharksimo3324 thanks
Hey every1, I have a problem:
I know someone actually had this problem in the comments before, but the answer didn't help me that much due to me being quite new to coding, but my character keeps getting stuck on collision boxes, with only up being the way out, which then completely stucks the pCharacter in the collision box up top of the pCharacter. Can someone help?
same problem, have you found the solution?
@@adrianrazvan17 actually yes, i've made seperate boolians for collisionOnUp/Down/Left/Right and coded them in the right places,
switch(direction) {
case "up":
if(collisionOnUp == false) {
worldY -= speed;
}
break;
case "down":
if(collisionOnDown == false) {
worldY += speed;
}
break;
case "left":
if(collisionOnLeft == false) {
worldX -= speed;
}
break;
case "right":
if(collisionOnRight == false) {
worldX += speed;
}
break;
}
now it works like a charme
How can I troubleshoot by drawing the collision rectangles on screen. My character is able to pass through top left and bottom left of solid objects.
You can display the rectangle by adding a line like this:
g2.drawImage(image, screenX, screenY, gp.tileSize, gp.tileSize, null); // Draw player
g2.fillRect(screenX + solidArea.x, screenY + solidArea.y, solidArea.width, solidArea.height); // Draw collision rectangle
@@RyiSnow Thanks. I finally figured out.
Thanks, this was very helpful. I had a similar problem and apparently the solidArea causes trouble if x,y, width and height are not set to numbers but to variables/calculations. I wanted to make it dependent on the tileSize and if, for example, I write
solidArea.width = (int) (Math.round(32/48*gp.tileSize));
the collission does not work properly and the collision rectangle is not painted at all.
However, with
solidArea.width = 42; (for tilesize 64)
all works fine.. A bit strange but at least now I know what's the problem :)
@@TerminallyUnique95 hey i am having a similar problem can you tell me how you solved it ?
@@geoartop3363 I had to recheck the code in checkTile until I found what I typed wrong.
I have a problem with the movement of the player. When I run the program the player doesn't stop moving. This only happens when I change the worldX and worldY to the if(collisionOn == false), any solutions?
nvm I had to put the, if(keyH.upPressed == true) around the speed in the case
I have a question, how do you limit if player reach the maximum world? How to make player not seeing a black screen?
This is late, but what you would need is a thick border of trees to where you can not go past to see the black screen. If you don't like this, you could incorporate a new grass tile that looks the same, but its collision is set to true, that way you will have an invisible border.
Hello, I have a problem where if I try to move, my character gets teleported to the left side of the map
Please turn on subtitles for this video!
Thank you so much!
Hmm those subtitles are auto-generated by CZcams so I'm not sure why this video doesn't have one. Maybe a glitch?
@@RyiSnow you have to enable it in your video settings
@@Melvin-14 As far as I know there's no option to enable auto-generated subtitles. You can only manually add subtitles.
If you think I'm missing something, let me know how to do it then I'll check it again.
@@RyiSnow yes but can u check ur latest video to see my comment i need help
when i hold W i cannot change direction unless i release W,when i hold etc D or A i can change direction by pressing W or S and i dont need to relase any key to change it,what may be the issue?
it is same with S,i cant figure out why A and D works but W and S doesnt
In checkTile is an error when I write Entity entity, so I need to write Player, it’s that normal?
If player is the only entity that you check collision, writing Player is fine but if you use the method to check other entities such as npcs or monsters (which we will do in later videos), it will cause problems.
@@RyiSnow I don’t know what I do, but now it’s working!
In tutorial 14 it start working
You could also move setting the image and collision into the constructor of tile, and just pass in the tile name to the Tile constructor, then in the getResourceAsStream you just pass in "/tiles/+name+".png". My list in the getTileImage became like this then:
public void getTileImage() {
tiles[0] = new Tile("grass", false);
tiles[1] = new Tile("brickwall", true);
tiles[2] = new Tile("water", true);
tiles[3] = new Tile("earth", false);
tiles[4] = new Tile("sand", false);
tiles[5] = new Tile("tree", true);
}
And my Tile class:
public class Tile {
public String name;
public BufferedImage image;
public boolean collision;
public Tile(String name, boolean collision) {
this.name = name;
this.collision = collision;
this.image = getImage();
}
private BufferedImage getImage() {
BufferedImage image = null;
try {
image = ImageIO.read(getClass().getResourceAsStream("/tiles/" + name + ".png"));
} catch (IOException e) {
e.printStackTrace();
}
return image;
}
}
Hi, I hope I could get help. When I start the game I can only move on W and when I press A, S or D the animation works but player wont move. But when I move around sometimes my player won't move and sort of get stuck because of som invicible collider. Btw you're touturials are amazing and I've learnt so much!
make sure you put double equal signs in the if statement: if(collisionOn == false)
I got it working, the collider was just offset by two tiles for some reason so I just expanded the game screen so it was 16 x 16 tiles instead of 16 x 12 but I can't find the problem why it was that
@@cristiano1296 spent two days trouble shooting and this was my issue thank u so much
@@LutherCraft222 i still have the issue i dont know how to fix it please help
@@zeishirou did you fix?
thank you for adding collision. i want ed this tutorial from you i make comment before about collision
Hope this helped!
I have a question.
After i copied that, the collisions are not activied but in walls, water and trees, my character keeps walking but it goes slower and I don't understand why, since we didn't deal with speed in the methods, has anyone come across a similar stuff?
Same here! Checked out comments section for a solution. I hope someone will help us. 🥶
Update : found this kinda working : case "up":
entityTopRow = (entityTopWorldY - entity.speed)/ GamePanel.tileSize;
tileNum1 = gp.tileM.mapTileNum[entityLeftCol][entityTopRow];
tileNum2 = gp.tileM.mapTileNum[entityRightCol][entityTopRow];
if (gp.tileM.tile[tileNum1].collision || gp.tileM.tile[tileNum2].collision) {
entity.collisionOn = true;
entity.speed = 0;
} else {
entity.collisionOn = false;
entity.speed = 4;
}
break;
Do this for each direction.
@@silenceradieux3590 lifesaver.
Around 11:41 I'm a little confused about what you're doing with those variables. I understand that the actual collision box is a smaller box inside the player box, but what are you trying to with these points? I've watched this video three times and I haven't managed to wrap my head around it.
Let's start from 11:41. After you input direction, the player's position is updated. Suppose you are on 23, 22 in the world map and press the up direction which updates the player position to 23, 21. You multiply these tile coordinates for the new position by the tile size 48 to get the pixel coordinates (1104,1008). You then use the offsets in the hitbox to determine the 4 corners that make up the coordinates of the player's collision box on the map. I'm using the actual values here for this situation but don't get hung up on that because they change everytime the player moves:
top of the box: 1008+16
bottom of the box: 1008 +48
left of box: 1104+8
right of box: 1104+40
The end result is a smaller box within the 48x48 tile that we use to draw the player sprite, which makes it easier not to bump into impassable tiles.
Here's the part I think you're asking about: Since you're hypothetically trying to move up in this example, we check the tiles on the upper left and upper right corner of the player's hitbox which are (1112, 1024) and (1144, 1024). We then divide these coordinates by the tile size to find out what their position is on the 50 x 50 game map in the text file and what type of tiles they are. It's possible for the left upper hitbox to fall in one tile and the right upper side of the hitbox to fall in a different tile so we have to check what the tile is at both coordinates to see whether they're passable, but in this case the entire hitbox falls inside one tile which is 23, 21 and that's a sand tile.
If the tiles are impassible the player isn't allowed to move there and you stay at position 23 ,22 or else it is passable and the player moves up to position 23, 21. Is that sort of what you were asking about?
@@jimmyjakes1823 Thank you for the explanation! I think I'm really beginning to understand things now!
Will you release the source code for this project? I'm having errors with the collision detection part of the tutorial and comparing the code would really help me.
the code is on the screen bro.....
I tried to optimize it but it dont worked and now i dunno whats wrong but if i hit a wall or somthing solid i cant move at any direction at all.
Found why.
whatHapend(?) {
iHaveTheSameProblem;
}
how can the player move diagonally, thanks so much!!
I am further along in the series but when I try to run my program now I am getting this error : * Exception in thread "Thread-0" java.lang.ArrayIndexOutOfBoundsException: Index 1048 out of bounds for length 50
at Main.CollisionChecker.checkTile(CollisionChecker.java:38)
at Entity.Player.update(Player.java:116)
at Main.GamePanel.update(GamePanel.java:113)
at Main.GamePanel.run(GamePanel.java:93)
at java.base/java.lang.Thread.run(Thread.java:833) */ and my mapTileNum = new int[maxWorldCol][maxWorldRow] ----- any ideas what could be causing this?
The program is trying to read the array with the index number 1048 which is way over the array's length ([50]). So my guess is you forgot to convert worldX/Y to Col/Row.
@@RyiSnow sorry to keep bugging you, I just want it to work lol and I really, really appreciated your tutorial. It helped me so much ! this is my public Tile Manager -------
@@RyiSnow what?
I'm wondering how I can draw the collision rectangle on the screen. Can someone help me?
im facing an issue where after the collision the player is not able to move in any direction
can you please tell me where did i go wrong?
when i comment out 3 of the cases in the collision detector class, the one direction which is running runs fine and the player doesn't get stuck
My collisionOn in the update method of player will not allow me to write it without "boolean" in front, it also will not let me do entity.collisionOn in collision checker.
is collisionOn in entity is set to public ? If yes then there must be spelling mistake perhaps.
Hey, I have an issue please tell me if i can paste the code in the replies. It enables collision when i walk forward with the w key and i cant walk any way after I do that, its really weird. I also wanted to know which version of java you use, is that what's causing the problem?
Sure you can paste your code here but sometimes CZcams automatically removes comments that include code so fingers crossed it will work. In any case, your issue sounds like your collisionOn status is not handled properly and the player character is getting stuck in collisionOn = true state. The boolean has to be set false when no collision is happening so I think that's where you want to check first. My guess is either you forgot to reset the boolean or the checkTile method failed to prevent the player from getting into a solid tile.
I'm pretty sure the java version has nothing to do with your issue.
@@RyiSnow Here is my code for collisionchecker:
package main;
import entity.Entity;
public class CollisionChecker {
GamePanel gp;
public CollisionChecker(GamePanel gp) {
this.gp = gp;
}
public void checkTile(Entity entity) {
int entityLeftWorldX = entity.worldX + entity.solidArea.x;
int entityRightWorldX = entity.worldX + entity.solidArea.x + entity.solidArea.width;
int entityTopWorldY = entity.worldY + entity.solidArea.y;
int entityBottomWorldY = entity.worldY + entity.solidArea.y + entity.solidArea.height;
int entityLeftCol = entityLeftWorldX / gp.tileSize;
int entityRightCol = entityRightWorldX / gp.tileSize;
int entityTopRow = entityTopWorldY / gp.tileSize;
int entityBottomRow = entityBottomWorldY / gp.tileSize;
int tileNum1, tileNum2;
switch (entity.direction) {
case "up":
entityTopRow = (entityTopWorldY - entity.speed) / gp.tileSize;
tileNum1 = gp.tileM.mapTileNum[entityLeftCol][entityTopRow];
tileNum2 = gp.tileM.mapTileNum[entityRightCol][entityTopRow];
if (gp.tileM.tile[tileNum1].collision == true || gp.tileM.tile[tileNum2].collision == true) {
entity.collisionOn = true;
}
break;
case "down":
entityBottomRow = (entityBottomWorldY + entity.speed) / gp.tileSize;
tileNum1 = gp.tileM.mapTileNum[entityLeftCol][entityBottomRow];
tileNum2 = gp.tileM.mapTileNum[entityRightCol][entityBottomRow];
if (gp.tileM.tile[tileNum1].collision == true || gp.tileM.tile[tileNum2].collision == true) {
entity.collisionOn = true;
}
break;
case "left":
entityLeftCol = (entityLeftWorldX - entity.speed) / gp.tileSize;
tileNum1 = gp.tileM.mapTileNum[entityLeftCol][entityTopRow];
tileNum2 = gp.tileM.mapTileNum[entityLeftCol][entityBottomRow];
if (gp.tileM.tile[tileNum1].collision == true || gp.tileM.tile[tileNum2].collision == true) {
entity.collisionOn = true;
}
break;
case "right":
entityRightCol = (entityTopWorldY + entity.speed) / gp.tileSize;
tileNum1 = gp.tileM.mapTileNum[entityRightCol][entityTopRow];
tileNum2 = gp.tileM.mapTileNum[entityRightCol][entityBottomRow];
if (gp.tileM.tile[tileNum1].collision == true || gp.tileM.tile[tileNum2].collision == true) {
entity.collisionOn = true;
}
break;
}
}
}
@@wandow this is my problem too do you have a solution yet?
No. 😭
I need help please. So no matter what key I am pressing my character jumps to the most left side of the map and gets stuck in the solid wall object.
I found the problem! I put an equals where there shouldv'e been a plus hahaha
@@justinabraham5642 to where
I guess I may have changed something I did not mean to change, because now I can walk through the tree tile. Any suggestions on what I can do?
If it is only trees it sounds like the mistake is in the TileManager class. Have you checked so that your tree tile has the line tile[5].collision= true;
My tree is [5] but it might be different for you.
hey i have a problem with the collisions my code is exacly like yours and when i run the program my character moves only left and when he reaches a tree it dont stop how can i fix it ?
or at least can somebody help me :/
@@sonnystoyanov1884 check if you have used correct variables in the switch case statement in the checkTile method inside the CollisionChecker class. To be precise I also wrote entityTopRow after the case "right": instead of entityRightCol and had similar problem.
Do you know what would cause my player to continue moving in the direction with out me pressing any keys? the collision works and it stops but if i move another direction the player will just keep walking in the direction i push
The player keeps walking most likely means one of the keyPressed boolean stays in true. So check around the keyPressed conditions.
@@RyiSnow thanks for the reply
public void update() {
if (keyH.upPressed == true|| keyH.downPressed == true ||
keyH.leftPressed == true || keyH.rightPressed == true) {
}
if (keyH.upPressed == true) {
direction = "up";
}
else if (keyH.downPressed == true) {
direction = "down";
}
else if (keyH.leftPressed == true) {
direction = "left";
}
else if (keyH.rightPressed == true) {
direction = "right";
}
collisionOn = false;
gp.cChecker.checkTile(this);
if(collisionOn == false){
switch(direction) {
case "up": worldY -= speed;
break;
case "down" : worldY += speed;
break;
case "left" : worldX -= speed;
break;
case "right": worldX += speed;
break;
}
} this is what i have current..
yeah still no luck =/ think i will have to watch a few times to find the fix. im able to control where it moves but i dont press anything its moving on its own
here is my key handler class as well package main;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class KeyHandler implements KeyListener {
public boolean upPressed, downPressed, leftPressed, rightPressed;
p
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == KeyEvent.VK_W) {
upPressed = true;
}
if (code == KeyEvent.VK_S) {
downPressed = true;
}
if (code == KeyEvent.VK_A) {
leftPressed = true;
}
if (code == KeyEvent.VK_D) {
rightPressed = true;
}
}
@Override
public void keyReleased(KeyEvent e) {
int code = e.getKeyCode();
if (code == KeyEvent.VK_W) {
upPressed = false;
}
if (code == KeyEvent.VK_S) {
downPressed = false;
}
if (code == KeyEvent.VK_A) {
leftPressed = false;
}
if (code == KeyEvent.VK_D) {
rightPressed = false;
}
}
}