В настоящее время я пытаюсь изучить F# и пытаюсь сделать очень простую игру, в которую можно играть на консоли. Я пытаюсь настроить и запустить элементарное обнаружение столкновений, которое я планировал работать как таковое:
Каждый элемент с определенным тегом в списке игровых объектов будет повторяться, и если будет обнаружено, что другой элемент в списке игровых объектов имеет ту же координату, что и первый объект, первый объект будет возвращен в его старое положение.
Итак, тип примерно такой:
type Object = {
x : int;
y : int;
model : char;
}
И каждый объект в игре использует этот тип в списке игровых объектов (объекты имеют метод обновления и т. д.). Однако при попытке выполнить обнаружение столкновений я борюсь с подходом, поскольку ни одна из операций списка по умолчанию действительно не работает, и я предполагаю, что я нужно каким-то образом сопоставить шаблон для определенного тега, а затем снова пройтись по списку, проверяя совпадение в координатах?
Любые идеи или указатели или помощь любого рода будут высоко оценены.
Не совсем понятно, что вы хотите сделать, но следующий пример должен дать вам некоторое представление.
Я предполагаю, что у вас есть 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
.
Я думаю, что что-то в этом роде подойдет:
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
.
Спасибо, мое объяснение проблемы было не совсем хорошим, извините, но это был именно тот подход, который я искал, спасибо!