You're mistakes seems to be in the place inwhich you try to handle Collision detection.
Firstly, your collision detection object is never going to work because when you reference a class object (clsGame, clsPlayer) you are referencing the actual set of code rather than an Instance of that object (so you can call static functions, sub routines, and use Static values, but it isn't declared as an instance of the object and therefore would have no values in it, and really doesn't mean much). I am not sure how that changes when you use the Friend keyword, or why it allows you to access friend members in that way, but I can assure you that the collision code you have is incorrect.
So, the problem that I see you have made is WHERE you want to do the collision detection and WHAT OBJECTS you are referencing to do the check.
In most games, the collision detection must happen in a place where both the Player object and properties are available and the Level object is available. Some of that collision detection is broken up as (for instance, you allow a player to move into a square with an enemy, but the enemies collision detection sees that the player now resides in his square allowing the enemy to attack the player and push him back, this collision check happened on the Enemy rather than on the player)... Etc... In your case, since the player and the level tiles are available in the ClsGame object, that is where I propose you do your collision check. Here is a copy/paste/edited version of what you posted:
(I removed the shared keywords, I am guessing, from observing your code, that you don't know what that does and only did it because the IDE told you something like "Cannot access non-friend member" and to fix your clsCollsion class being broken, maybe I am wrong)
New clsGame Code looks like this: [code] Public Class clsGame Public GameForm As Form Public player As New clsSprite("player") Public map As New clsMap("Home.map", "Basis") Public Const TileWidth As Integer = 30 Public Const TileHeight As Integer = 30 Public Sub New(ByVal frm As Form) GameForm = frm End Sub
Public Function Allow(ByVal direction As clsSprite.Dir) As Boolean Select Case direction Case clsSprite.Dir.Up If Me.player.TilePos.Y = 0 Then Return False If Me.map.Passable(Me.player.TilePos.X, Me.player.TilePos.Y - 1) Then Return True Else Return False End If Case clsSprite.Dir.Down If Me.player.TilePos.Y = Me.map.Height / 30 Then Return False If Me.map.Passable(Me.player.TilePos.X, Me.player.TilePos.Y + 1) Then Return True Else Return False End If Case clsSprite.Dir.Left If Me.player.TilePos.X <= 0 Then Return False If Me.map.Passable(Me.player.TilePos.X - 1, Me.player.TilePos.Y) Then Return True Else Return False End If Case clsSprite.Dir.Right If Me.player.TilePos.X = Me.map.Width / 30 Then Return False If Me.map.Passable(Me.player.TilePos.X + 1, Me.player.TilePos.Y) Then Return (True) Else Return False End If End Select End Function
End Class [/code]
in the Main form, I implement this Allow function as follows: [code] Private Sub Main_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown Select Case e.KeyCode Case Keys.Up If Game.Allow(clsSprite.Dir.Up) Then player.MoveUp() Case Keys.Down If Game.Allow(clsSprite.Dir.Down) Then player.MoveDown() Case Keys.Left If Game.Allow(clsSprite.Dir.Left) Then player.MoveLeft() Case Keys.Right If Game.Allow(clsSprite.Dir.Right) Then player.MoveRight() End Select Me.Text = "Current Position: " & player.Position.ToString() End Sub [/code]
Now, you check that the player is allowed to move somewhere before he actually does the action.
Hope this helps, Note that I did not test that this works, I feel pretty confident it will though.
You've got a good start here, good luck and happy coding Sean Campbell
Well, I really apriciate it that you took the time to help me, but it still doesn't work =/ The player still is walking trought tiles where he normally can't walk trough =S
Please provide me with a copy of the current version of the Project that is still not working and I will take another look at it and tell you what I see.
Comments
Firstly, your collision detection object is never going to work because when you reference a class object (clsGame, clsPlayer) you are referencing the actual set of code rather than an Instance of that object (so you can call static functions, sub routines, and use Static values, but it isn't declared as an instance of the object and therefore would have no values in it, and really doesn't mean much). I am not sure how that changes when you use the Friend keyword, or why it allows you to access friend members in that way, but I can assure you that the collision code you have is incorrect.
So, the problem that I see you have made is WHERE you want to do the collision detection and WHAT OBJECTS you are referencing to do the check.
In most games, the collision detection must happen in a place where both the Player object and properties are available and the Level object is available. Some of that collision detection is broken up as (for instance, you allow a player to move into a square with an enemy, but the enemies collision detection sees that the player now resides in his square allowing the enemy to attack the player and push him back, this collision check happened on the Enemy rather than on the player)... Etc... In your case, since the player and the level tiles are available in the ClsGame object, that is where I propose you do your collision check. Here is a copy/paste/edited version of what you posted:
(I removed the shared keywords, I am guessing, from observing your code, that you don't know what that does and only did it because the IDE told you something like "Cannot access non-friend member" and to fix your clsCollsion class being broken, maybe I am wrong)
New clsGame Code looks like this:
[code]
Public Class clsGame
Public GameForm As Form
Public player As New clsSprite("player")
Public map As New clsMap("Home.map", "Basis")
Public Const TileWidth As Integer = 30
Public Const TileHeight As Integer = 30
Public Sub New(ByVal frm As Form)
GameForm = frm
End Sub
Public Function Allow(ByVal direction As clsSprite.Dir) As Boolean
Select Case direction
Case clsSprite.Dir.Up
If Me.player.TilePos.Y = 0 Then Return False
If Me.map.Passable(Me.player.TilePos.X, Me.player.TilePos.Y - 1) Then
Return True
Else
Return False
End If
Case clsSprite.Dir.Down
If Me.player.TilePos.Y = Me.map.Height / 30 Then Return False
If Me.map.Passable(Me.player.TilePos.X, Me.player.TilePos.Y + 1) Then
Return True
Else
Return False
End If
Case clsSprite.Dir.Left
If Me.player.TilePos.X <= 0 Then Return False
If Me.map.Passable(Me.player.TilePos.X - 1, Me.player.TilePos.Y) Then
Return True
Else
Return False
End If
Case clsSprite.Dir.Right
If Me.player.TilePos.X = Me.map.Width / 30 Then Return False
If Me.map.Passable(Me.player.TilePos.X + 1, Me.player.TilePos.Y) Then
Return (True)
Else
Return False
End If
End Select
End Function
End Class
[/code]
in the Main form, I implement this Allow function as follows:
[code]
Private Sub Main_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
Select Case e.KeyCode
Case Keys.Up
If Game.Allow(clsSprite.Dir.Up) Then player.MoveUp()
Case Keys.Down
If Game.Allow(clsSprite.Dir.Down) Then player.MoveDown()
Case Keys.Left
If Game.Allow(clsSprite.Dir.Left) Then player.MoveLeft()
Case Keys.Right
If Game.Allow(clsSprite.Dir.Right) Then player.MoveRight()
End Select
Me.Text = "Current Position: " & player.Position.ToString()
End Sub
[/code]
Now, you check that the player is allowed to move somewhere before he actually does the action.
Hope this helps, Note that I did not test that this works, I feel pretty confident it will though.
You've got a good start here, good luck and happy coding
Sean Campbell
The player still is walking trought tiles where he normally can't walk trough =S
-Sean Campbell
Thank you very much on solving my problem =D
Good luck sir!
-Sean Campbell
firesickle.com