Reputation: 149
I have an issue. I am currently learning Haskell, and trying to build a dungeon game.
Currently I am trying to implement a movement function for the player. Before moving to a new position,I must check if the player's new position will collide with the position of an object on the map of the game.
The code I have in my head (in Java/C) is fairly simple, yet I cannot think how it would cross over to Haskell. I'm pretty sure there's an alternative approach using Haskell code but this is the rough idea (Java/C):-
Let's assume the player object has x and y coordinates.
Let's also assume we store a list of other objects that the player may collide with in an array (this would be stored in a list for Haskell, I assume). Also, lets assume each object has an x and y co-ordinate.
The Boolean function returns true
if a collision will occur, or false
if not.
Boolean detectCollision(Player p, Object[] o)
{
for(int i=0; i < o.length; i++){
if(p.x==o[i].x && p.y==o[i].y){
return true;
}
} return false;
}
If someone could help me figure this out I'd be very grateful.
Upvotes: 3
Views: 668
Reputation: 54058
Even if this were Java/C, I would recommend that you write a function that detects if a player and a single object would collide, so let's do that here:
collidesWith :: Player -> Object -> Bool
collidesWith player object =
playerX player == objectX object && playerY player == objectY object
This is a little wordy, you can shorten this using the lens
library to actually make it look like
collidesWith player object
= player^.x == object^.x && player^.y == object^.y
But this is outside the scope of this question, just know that it's fully possible in Haskell.
For "looping" over a list in Haskell you can use recursion
detectCollision player [] = False -- No objects, no collisions
detectCollision player (o:objects)
= player `collidesWith` o || detectCollision player objects
Since Haskell is lazy, the first time player `collidesWith` o
evaluates to True
it will stop checking. But this actually already exists as a standard built in function named any
:
any :: (a -> Bool) -> [a] -> Bool
And can be used as
detectCollision player objects = any (collidesWith player) objects
Haskell even lets you drop the objects
argument through eta reduction, so it can be written simply as
detectCollision :: Player -> [Object] -> Bool
detectCollision player = any (collidesWith player)
And that's it!
Note: This is assuming that Player
and Object
are defined as
data Player = Player
{ playerX :: Int
, playerY :: Int
} deriving (Eq, Show)
data Object = Object
{ objectX :: Int
, objectY :: Int
} deriving (Eq, Show)
Upvotes: 7