比较列表中每个元素的值与列表中每个其他元素的值并对其进行更新(f#)

时间:2019-01-23 23:26:59

标签: f# pattern-matching collision-detection

我目前正在尝试学习F#,并且试图在控制台中进行一个非常简单的游戏。我正在尝试启动并运行一些基本的碰撞检测程序,而我打算这样工作:

将迭代游戏对象列表中具有特定标签的每个元素,并且如果发现游戏对象列表中的另一个元素与第一个对象共享相同的坐标,则第一个对象将放回原来的位置

所以类型是这样的:

type Object = {
x : int;
y : int;
model : char;
}

并且游戏中的每个对象在游戏对象列表中都使用这种类型(对象具有更新方法等。)但是,当尝试进行碰撞检测时,我正在尝试一种方法,因为默认列表操作都不起作用,我假设我需要以某种方式对特定标记进行模式匹配,然后再次遍历列表以检查坐标是否匹配?

我们将不胜感激任何想法,指针或任何形式的帮助。

2 个答案:

答案 0 :(得分:0)

目前尚不清楚您要做什么,但是下面的示例应该可以使您有所了解。

我假设您有objects,这是游戏中所有对象的列表。这包括一个要移动的具有给定model值的对象。以下函数将modelToMove作为参数(用于标识应移动的对象)以及该对象的新X和Y坐标以及所有对象的列表。

如果在新的X和Y坐标处有某些内容,它将仅返回原始对象。否则,它将具有给定model的对象移动到新位置:

let moveObject modelToMove (newX, newY) objects = 
  let blocked = objects |> List.exists (fun o -> o.x = newX && o.y = newY)
  if blocked then objects 
  else  
    objects |> List.map (fun o ->
      if o.model = modelToMove then { o with x = newX; y = newY }
      else o)

要检查头寸是否被冻结,我们使用List.exists。要使用新的更新对象位置创建列表,请使用List.map

答案 1 :(得分:0)

我认为可以遵循以下原则:

type GameObjectType =
    | Player
    | Bullet
    | Wall
    // etc.

type Position =
    {
        x : int
        y : int
    }

type GameObject =
    {
        objectType : GameObjectType
        position : Position
    }

type Rectangle = Position * Position // rectagle is defined by two opposite corners.

type IntersectionResult =
    | NoIntersection
    | Rectangle of Rectangle

type CollisionHandler =
    {
        intersect : GameObject -> GameObject -> IntersectionResult
        handleCollision : (GameObject * GameObject) -> Rectangle -> (GameObject * GameObject)
    }

let handleCollisions (handler : CollisionHandler) (objects : List<GameObject>) =
    // Handle collision of two objects a and b.
    let handleCollision (a, b) =
        match handler.intersect a b with
        | NoIntersection -> (a, b)
        | Rectangle r -> handler.handleCollision (a, b) r

    // Handle collision of object a with the list c by iterating through
    // the list and updating position of object a and current element of the list r.
    let handleCollisions (a, c) =
        c
        |> List.fold (fun acc r -> 
                        let (n, m) = handleCollision (fst acc, r)
                        (n, m :: (snd acc))
                        ) (a, [])

    let rec inner processed remaining =

        match remaining with
        | [] -> processed
        | h :: t ->
            let (newH, newT) = handleCollisions (h, t)
            inner (newH :: processed) newT

    inner [] objects

您将需要提供函数来确定冲突:intersect以及如何处理它们:handleCollision中的CollisionHandler