Сравнение значений каждого элемента в списке с каждым другим элементом в списке и его обновление (f #) - PullRequest
0 голосов
/ 24 января 2019

Я сейчас пытаюсь выучить F # и пытаюсь сделать очень простую игру, в которую играют в консоли. Я пытаюсь запустить какое-то элементарное обнаружение столкновений, которое я планировал работать следующим образом:

Каждый элемент с определенным тегом в списке игровых объектов будет повторяться, и если будет найден другой элемент в списке игровых объектов, имеющий ту же координату, что и первый объект, первый объект будет возвращен в прежнее положение .

Итак, тип выглядит примерно так:

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

И каждый объект в игре использует этот тип в списке игровых объектов (у объектов есть метод обновления и т. Д.). Однако при попытке обнаружения столкновений я сталкиваюсь с подходом, поскольку ни одна из операций со списком по умолчанию действительно не работает, и я я предполагаю, что мне нужно каким-то образом сопоставить шаблон для конкретного тега, а затем выполнить итерацию по списку еще раз, проверяя совпадение по координатам?

Любые идеи или указатели или помощь любого рода будут наиболее ценными.

Ответы [ 2 ]

0 голосов
/ 24 января 2019

Я думаю, что что-то в этом роде подойдет:

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.

0 голосов
/ 24 января 2019

Не совсем понятно, что вы хотите сделать, но следующий пример должен дать вам некоторое представление.

Я предполагаю, что у вас есть 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.

...