OUR OFFICIAL WEBSITE: https://dsgamemaker.online - ONLINE


WARNING! YOU WILL BE BANNED WITHOUT WARNING PERMENANTLY FOR SPAMMING THE FORUM WITH NON-DSGM RELATED TOPICS & POSTS! - FULLY ENFORCED!!!

NOTICE: ALL members that have NOT logged in once since their activation within 5 days have been and will be deleted!!! LAST UPDATED: 5-1-2022

NOTICE: I will NOT be sending anymore emails confirming your account being activated.. Try to log in and see if your account was activated yet..

ALL accounts MUST be Admin activated due to the server we are on! - More info in the announcements section

Please read announcements section of the forum upon logging in to stay up to date

Side note: Just a reminder, 4.9 and 5.12 are 2 totally different programs. You cannot use 1 app to load projects from the other.

NPC Collision

Discussions and support SPECIFICALLY for version 5.12 only
Post Reply
TheRetroRoomRoo
Newbie
Newbie
Posts: 11
Joined: Sat Mar 13, 2021 6:47 am

NPC Collision

Post by TheRetroRoomRoo »

Hey. I hope everyone is well. :) I come to the community with another simple concept. I have created NPC1 and NPC2 objects as well as a Player object... On my player object I have created character controls that go as follows...
If Pad.Held.Right
if !Sprite_Collision([Me], Get_Single_ID(NPC1))
if !Sprite_Collision([Me], Get_Single_ID(NPC2))
if(PA_EasyBgGetPixelCol(Top_Screen, 3,[X] + [Width], [Y] + [Height]/2)!= PA_RGB(0,0, 0)){
If !Object_Under_Point(Top_Screen, [X]+[Width], [Y]+[Height]/2, NPC1)
[X] += 2;
End if
End if
End if
End if
}

If Pad.Held.Left
if !Sprite_Collision([Me], Get_Single_ID(NPC1))
if !Sprite_Collision([Me], Get_Single_ID(NPC2))
if(PA_EasyBgGetPixelCol(Top_Screen, 3,[X], [Y] + [Height]/2)!= PA_RGB(0,0, 0)){
If !Object_Under_Point(Top_Screen, [X]+[Width], [Y]+[Height]/2, NPC1)
[X] -= 2;
End if
End if
End if
End if
}
This is to look out for the other NPC characters as well as as the other layers in the level for a collision map.
All of the collisions for the collision map work well... My problem is with the player getting stuck on the NPC characters. When they collide my player gets stuck ESPECIALLY if I add collision checks for "up" and "down" on top of these "left" and "right" collision checks.
Is there a better way for me to do this? Am I heading into the right direction? I wouldnt mind even getting rid of collisions on NPC characters all together if I had the availability to allow the player object in front of or behind objects based upon where they are on the X axis..

If anyone could shoot some advice my way, that would be amazing! Thanks so much! :D
User avatar
DigitalDesignDude
Appreciated Member
Appreciated Member
Posts: 84
Joined: Sun Aug 16, 2020 6:02 am

Re: NPC Collision

Post by DigitalDesignDude »

@TheRetroRoomRoo, I would say you’re off to a good start for your collision code. :) You just need to remove the “if Sprite_Collision” statements from your player object to prevent it from becoming stuck to the NPC1 and NPC2 forever when they collide.

The problem with your If Sprite_Collision statements is they only allow the player to move so long as it’s not collided with NPC objects.

Meaning of course if they ever do collide, then the player will be stuck as you’re noticing and will not be able to even move away from the NPC.

So rather than coding: “The player can move so long as it never touches an NPC”

Change it to: “The player can move so long as the space it wants to move to is not occupied by an NPC”

To do that you need to use the If Object_Under_Point or Under Line functions to check if an NPC is at a specific x and y location or line between two coordinates.

I see you already have an If !Object_Under_Point check for NPC1 so do the same with NPC2 as well.

Also, I would recommend using the The Object Under Line check instead since you can then check to see if the space available is a big as a line equal to the Player’s width/height. It’s more accurate that way than checking If an single x and y point is unoccupied. Alternatively, you could use multiple if !Object Under Points statements if you prefer that instead.

Is there a better way for me to do this?
Though it isn’t necessarily better, another way of preventing the player from walking through NPCs is by using a CanMove bool Variable which controls whenever the player is allowed to move. However this has given me quite a few problems in the past so I don’t recommend it much, but you’re welcome to experiment with it.


I wouldnt mind even getting rid of collisions on NPC characters all together if I had the availability to allow the player object in front of or behind objects based upon where they are on the X axis


You can actually set the layer an object’s sprite is on using the “Set Sprite Priority or Layer” Function. I can’t remember it’s exact name but you should be able to find it in the Palib Documentation.
Multimedia Developer & Designer and Former DSGM 5.12 User

Created DS Games: BioDie, Fishing the Deep

Email notifications not currently supported on this forum.
Discord: DDesignDude#0055
TheRetroRoomRoo
Newbie
Newbie
Posts: 11
Joined: Sat Mar 13, 2021 6:47 am

Re: NPC Collision

Post by TheRetroRoomRoo »

I definitely appreciate it as usual DigitalDesignDude! I tried adding the !object under point code for both NPC1 and NPC2 and I tried removing the sprite collision lines and my player is still getting stuck. I am trying to understand how to reorganize it to be like you mention , the player can move as long as the space is not already occupied, but I cant seem to get it correctly. Here is the code as it stands.....do I need to change around where the actual movement happens in my script?
If Pad.Held.Right
if !Sprite_Collision([Me], Get_Single_ID(NPC1))
if !Sprite_Collision([Me], Get_Single_ID(NPC2))
if(PA_EasyBgGetPixelCol(Top_Screen, 3,[X] + [Width], [Y] + [Height]/2)!= PA_RGB(0,0, 0)){
If !Object_Under_Point(Top_Screen, [X]+[Width], [Y]+[Height]/2, NPC1)
If !Object_Under_Point(Top_Screen, [X]+[Width], [Y]+[Height]/2, NPC2)
[X] += 2;
End if
End if
End if
End if
End if
}

If Pad.Held.Left
if !Sprite_Collision([Me], Get_Single_ID(NPC1))
if !Sprite_Collision([Me], Get_Single_ID(NPC2))
if(PA_EasyBgGetPixelCol(Top_Screen, 3,[X], [Y] + [Height]/2)!= PA_RGB(0,0, 0)){
If !Object_Under_Point(Top_Screen, [X]+[Width], [Y]+[Height]/2, NPC1)
If !Object_Under_Point(Top_Screen, [X]+[Width], [Y]+[Height]/2, NPC2)
[X] -= 2;
End if
End if
End if
End if
End if
}

If Pad.Held.Up
if !Sprite_Collision([Me], Get_Single_ID(NPC1))
if !Sprite_Collision([Me], Get_Single_ID(NPC2))
if(PA_EasyBgGetPixelCol(Top_Screen, 3,[X] + [Width]/2, [Y])!= PA_RGB(0,0, 0)){
If !Object_Under_Point(Top_Screen, [X]+[Width], [Y]+[Height]/2, NPC1)
If !Object_Under_Point(Top_Screen, [X]+[Width], [Y]+[Height]/2, NPC2)
[Y] -= 2;
End if
End if
End if
End if
End if
}

If Pad.Held.Down
if !Sprite_Collision([Me], Get_Single_ID(NPC1))
if !Sprite_Collision([Me], Get_Single_ID(NPC2))
if(PA_EasyBgGetPixelCol(Top_Screen, 3,[X] + [Width]/2, [Y] + [Height])!= PA_RGB(0,0, 0)){
If !Object_Under_Point(Top_Screen, [X]+[Width], [Y]+[Height]/2, NPC1)
If !Object_Under_Point(Top_Screen, [X]+[Width], [Y]+[Height]/2, NPC2)
[Y] += 2;
End if
End if
End if
End if
End if
}
User avatar
DigitalDesignDude
Appreciated Member
Appreciated Member
Posts: 84
Joined: Sun Aug 16, 2020 6:02 am

Re: NPC Collision

Post by DigitalDesignDude »

Good to see you're still putting in good efforts @TheRetroRoomRoo. It can sometimes take a while to get things working the way we want to but we often learn so much through that process and feel more accomplished after it's all fixed :)

You shouldn't need to change where the movement code takes place in your player object so long as it's in the player's Step event and that there's no other code in your project controlling whether the player can and cannot move.

I reviewed and cleaned up the code I used from my NPCs Random Movement and Talk Example and it turns out I did use a variable to control when the player is blocked or not but the code without the variable is equivalent to using the below code.


Updated NPCs Random Movement and Talk Example
https://drive.google.com/drive/folders/ ... sp=sharing

Code: Select all

//If Right dpad button is held, move the player right so long as the collision map, NPC1, and NPC2 doesn't block the player's way.
if Pad.Held.Right
if(PA_EasyBgGetPixelCol(Top_Screen, 3,[X] + [Width] +2, [Y] + [Height]/2)!= PA_RGB(0,0, 0)){
if((!Object_Under_Point(Top_Screen, [X]+ [Width] + 2, [Y]+[Height]/2, NPC1)) && (!Object_Under_Point(Top_Screen, [X]+ [Width]+2, [Y]+[Height]/2, NPC2)) ){
 [X] = [X]+2;
End if
End if
End if


The difference between this code and your current code is:
  • There is no if Sprite_Collision statements
  • For my object collision checks, I'm using an && operator which checks if both NPC1 and NPC2 is not in the way of the player's movement at the same time.


However, I also noticed the code you previously shared is not using the proper X and Y values for the "If Object_Under_Point" statements for the UP, Down and Left Held conditions. That is likely causing you even more issues.

For example, here's what you have for the Up Button Held Condition:

Code: Select all

If !Object_Under_Point(Top_Screen, [X]+[Width], [Y]+[Height]/2, NPC1)
If !Object_Under_Point(Top_Screen, [X]+[Width], [Y]+[Height]/2, NPC2)
And here's what you should have this instead, in order to check for the point directly above the player:

Code: Select all

If !Object_Under_Point(Top_Screen, [X]+[Width]/2, [Y], NPC1)
If !Object_Under_Point(Top_Screen, [X]+[Width]/2, [Y], NPC2)

If you still have issues after consulting and trying out some of the theories from this post let me know and I may then have to look at your project file directly.
Multimedia Developer & Designer and Former DSGM 5.12 User

Created DS Games: BioDie, Fishing the Deep

Email notifications not currently supported on this forum.
Discord: DDesignDude#0055
User avatar
Ruffsta
Site Admin
Site Admin
Posts: 170
Joined: Fri May 22, 2020 6:21 am

Re: NPC Collision

Post by Ruffsta »

@DDD - ty for helping out around here...
DS Games:
BananaCraze / MasterMind / Rock,Paper, Scissors

*strictly a 4.9 user
TheRetroRoomRoo
Newbie
Newbie
Posts: 11
Joined: Sat Mar 13, 2021 6:47 am

Re: NPC Collision

Post by TheRetroRoomRoo »

Thanks a bunch for the help! I really appreciate the both of you for helping out a beginner. I think this might come in handy for others who come explore these forums. I think my X and Y values are still slightly off, but this is working a whole lot better than it was before. Now I am not getting the player stuck... but something is wrong with the X and Y on if going left... it doesnt stop me until I run the NPC over.
Here is my code:

Code: Select all

'Character controller
if Pad.Held.Right
if(PA_EasyBgGetPixelCol(Top_Screen, 3,[X] + [Width] +2, [Y] + [Height]/2)!= PA_RGB(0,0, 0)){
if((!Object_Under_Point(Top_Screen, [X]+ [Width] + 2, [Y]+[Height]/2, NPC1)) && (!Object_Under_Point(Top_Screen, [X]+ [Width]+2, [Y]+[Height]/2, NPC2)) ){
 [X] = [X]+2;
End if
End if
End if

If Pad.Held.Left
if(PA_EasyBgGetPixelCol(Top_Screen, 3,[X], [Y] + [Height]/2)!= PA_RGB(0,0, 0)){
If !Object_Under_Point(Top_Screen, [X]+[Width]+2, [Y]+[Height]/2, NPC1)
If !Object_Under_Point(Top_Screen, [X]+[Width]+2, [Y]+[Height]/2, NPC2)
[X] -= 2;
End if 
End if 
End if
}

If Pad.Held.Up
if(PA_EasyBgGetPixelCol(Top_Screen, 3,[X] + [Width]/2, [Y])!= PA_RGB(0,0, 0)){
If !Object_Under_Point(Top_Screen, [X]+[Width]/2, [Y], NPC1)
If !Object_Under_Point(Top_Screen, [X]+[Width]/2, [Y], NPC2)
[Y] -= 2;
End if 
End if 
End if
}

If Pad.Held.Down
if(PA_EasyBgGetPixelCol(Top_Screen, 3,[X] + [Width]/2, [Y] + [Height])!= PA_RGB(0,0, 0)){
If !Object_Under_Point(Top_Screen, [X]+[Width]/2, [Y]+[Height], NPC1)
If !Object_Under_Point(Top_Screen, [X]+[Width]/2, [Y]+[Height], NPC2)
[Y] += 2;
End if 
End if 
End if
}

TheRetroRoomRoo
Newbie
Newbie
Posts: 11
Joined: Sat Mar 13, 2021 6:47 am

Re: NPC Collision

Post by TheRetroRoomRoo »

I also need to rearrange things to use the && on Object under point.
User avatar
DigitalDesignDude
Appreciated Member
Appreciated Member
Posts: 84
Joined: Sun Aug 16, 2020 6:02 am

Re: NPC Collision

Post by DigitalDesignDude »

@TheRetroRoomRoo yes your X and Y values are still off for the Left movement. But good to see you got the Down, Up and Right values pretty much correct. The Up and Down values are just missing the added 2px offset which is good to include like you did for the Right x and y values.

With the way you currently have your Left collision check, it’s actually checking to see if an NPC is on the very right of the player instead of the left. Whoops :)

So we need to change the following:

Code: Select all

//Left Direction Check 
If !Object_Under_Point(Top_Screen, [X]+[Width]+2, [Y]+[Height]/2, NPC1)
To the below code, so that we are checking the left edge of the sprite minus the 2px that the player will be moving by.

Code: Select all

//Left Direction Check
If !Object_Under_Point(Top_Screen, [X]-2, [Y]+[Height]/2, NPC1)
Now the code will check if there’s an NPC1 occupying the space exactly 2 pixels to the left of the player horizontally and in the middle of the player vertically.

Here’s a breakdown example of why we have have to adjust our x and y values correctly whenever we do Object_Under_Point and Collision maps checks.

For an object that has a 16x32 sprite, is initially located at coordinates X: 64 and Y: -128 and is moving at 2px/Game frame, the following has to be kept in mind:
  • All objects in DSGM have their X and Y coordinates measured from the top left corner of their sprite!
  • The [X] Object Property code gives us the X position of an object’s top left corner. (Eg. 64)
  • The [Y] Object Property code gives us the Y position of the object’s top left corner. (Eg.-128)
  • The [Width] Object Property code gives us the Object’s total horizontal width of its sprite. (Eg. 16px)
  • The [Height] Object Property Code gives us the Object’s total vertical height of its sprite. (Eg. 32)
  • We add or substract 2px to our collision check coordinates since we are moving at 2px/frame, and in this way we are checking if the space 2px away from our player is occupied or not. This added offset makes movement And collisions more polished.
  • The farther Right an object moves in a game, the more positive its X position becomes.
  • The farther Down an object moves in a game, the more positive its Y position becomes. (That's backwards from regular graphs we learned about in elementary school)

By using the correct combination of object properties and movement offsets we then have the player object check for coordinates that are actually to the very left, right, bottom, or top edge of the player.

So with all this information you should be able to use the correct X and Y values for your collision checks. Just takes a little math ;)

Also it may not be necessary to use the && operator. If might be easier to just not use it if you find the code is working with separate if statements.
Multimedia Developer & Designer and Former DSGM 5.12 User

Created DS Games: BioDie, Fishing the Deep

Email notifications not currently supported on this forum.
Discord: DDesignDude#0055
TheRetroRoomRoo
Newbie
Newbie
Posts: 11
Joined: Sat Mar 13, 2021 6:47 am

Re: NPC Collision

Post by TheRetroRoomRoo »

@DigitalDesignDude thanks so much for the amazing explanation.. This definitely has fixed my issues as well as given me a deeper understanding of the function itself. Thank you! I suppose the last question is, is there a way to slim down the code (maybe using an array or something) to slim down the code if I add lets say 12-15 different NPC characters? Or should I just continue to stack the "IF" Statements? I really appreciate all the advice. It is greatly appreciated.
User avatar
DigitalDesignDude
Appreciated Member
Appreciated Member
Posts: 84
Joined: Sun Aug 16, 2020 6:02 am

Re: NPC Collision

Post by DigitalDesignDude »

@TheRetroRoomRoo There are a couple of ways you could slim down your collision code.

Method 1: Combine NPCs that share the same code but just have them use different Sprites

This is ideal if you have a lot of NPCs that say the same things and behave the same way but differ only by sprite art. You basically set the desired amount of NPC to be created in a room, and upon them being created you have them switch to a specific sprite or sprite frame that you want.

An example of this can be seen with the Bouncing Balls Example that's located in the DSGM 5.12 Examples folder on your Virtual Machine.
Every time a Ball is created it randomly selects a random sprite or sprite fame before being appearing in the game's room.



Method 2: Define your own Collision Function to reuse code but with different values

With a collision function we define, we can take the following code:

Code: Select all

if Pad.Held.Right
if(PA_EasyBgGetPixelCol(Top_Screen, 3,[X] + [Width] +2, [Y] + [Height]/2)!= PA_RGB(0,0, 0)){
If !Object_Under_Point(Top_Screen, [X]+[Width]+2, [Y]+[Height]/2, NPC1)
If !Object_Under_Point(Top_Screen, [X]+[Width]+2, [Y]+[Height]/2, NPC2)
[X] = [X]+2;
End if
End if
End if

If Pad.Held.Left
if(PA_EasyBgGetPixelCol(Top_Screen, 3,[X], [Y] + [Height]/2)!= PA_RGB(0,0, 0)){
If !Object_Under_Point(Top_Screen, [X]+[Width]+2, [Y]+[Height]/2, NPC1)
If !Object_Under_Point(Top_Screen, [X]+[Width]+2, [Y]+[Height]/2, NPC2)
[X] -= 2;
End if 
End if 
End if
}
And simplify it to this:

Code: Select all

if Pad.Held.Right
if CollisionCheck(([X] + [Width] +2), ([Y] + [Height]/2)) == false
[X] = [X]+2;
End if

If Pad.Held.Left
if CollisionCheck(([X] - 2), ([Y] + [Height]/2)) == false
[X] -= 2;
End if 
End if 
End if
}
We then define our CollisionCheck Function somewhere globally like in an external .h file that we add to the game settings' "Include Menu":

Code: Select all

'Here we are declaring a function called "CollisionCheck" which takes in any X and Y values and then returns/gives us a bool truth or false value based on what the function calculates.

bool CollisionCheck(int ValueX, int ValueY){
if(PA_EasyBgGetPixelCol(Top_Screen, 3,ValueX, ValueY)!= PA_RGB(0,0, 0)){
If !Object_Under_Point(Top_Screen, ValueX, ValueY, NPC1){
If !Object_Under_Point(Top_Screen, ValueX, ValueY, NPC2){
return false;
}
}
}
return true;


NOTE: This is just for educational purposes, I have not tested this code so you will likely run into errors if you just copy and paste this code into your project.

Unfortunately, I have not successfully declared functions directly in DSGM yet which is why I declare them in an external file, so you might not be able to use this method without a lot of trial and error should you decide to pursue it without an external file. I'm also not sure if external files are aware of object names declared in DSGM so it might not recognize NPC Object's names.

There is another way of simplifying your code without declaring a function but it's not as elegant. You basically create a bunch of variables that change values depending on which direction the player is facing and those variables are then used in place of the X and Y values used in the Collision if Statements. You then use a Blocked bool variable which changes value depending on if the collision if statements return true or false.
Multimedia Developer & Designer and Former DSGM 5.12 User

Created DS Games: BioDie, Fishing the Deep

Email notifications not currently supported on this forum.
Discord: DDesignDude#0055
Post Reply