Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

help mario64

A topic by shoshinsha created Nov 24, 2020 Views: 229 Replies: 2
Viewing posts 1 to 2
(2 edits)

I want to make a Mario 64-like game, but I do not understand how to reflect the keys.

Here is the source code I wrote.

```elm

-- MODEL

-- IDで役割を分ける。
type Id
    = Key
    | Player
    | Floor

-- Msgには何がいるのか
type Msg
    = AnimationFrame
    | Resize (Quantity Float Pixels) (Quantity Float Pixels)
    | KeyDown (Axis3d Meters WorldCoordinates)
    | KeyUp
    | Restart

init : () -> ( Model, Cmd Msg )
init _ =
    ({ world=initialWorld
    , width=pixels 0
    , height=pixels 0
    , maybeRaycastResult = Nothing
    , exposureValue = 0
    }
    , Task.perform
        (\{ viewport } ->
            Resize (pixels viewport.width) (pixels viewport.height)
        )
        Browser.Dom.getViewport
    )

-- WORLD
initialWorld: World Data
initialWorld=
    World.empty
        |> World.withGravity             (Acceleration.metersPerSecondSquared 9.80665)
            Direction3d.negativeZ
        |> World.add player
        |> World.add floorBody

key:Body Data
key =
    compound []
        { id = Key
        , entity =
            Scene3d.sphere (Material.matte Color.white)
                (Sphere3d.atOrigin (millimeters 20))}

decodeKeyRay:
    Camera3d Meters WorldCoordinates
    -> Quantity Float Pixels
    -> Quantity Float Pixels
    -> (Axis3d Meters WorldCoordinates -> msg)
    -> Decode.Decoder msg
decodeKeyRay camera3d width height rayToMsg =
    Decode.map2
        (\x y ->
            rayToMsg
                (Camera3d.ray
                    camera3d
                    (Rectangle2d.with
                        { x1 = pixels 0
                        , y1 = height
                        , x2 = width
                        , y2 = pixels 0
                        }
                    )
                    (Point2d.pixels x y)
                )
        )
        -- おそらくここにイベントリスナを書く
        (Decode.field "leftKey" Decode.float)
        (Decode.field "rightKey" Decode.float)

-- UPDATE

update : Msg -> Model -> Model
update msg model =
    case msg of
        AnimationFrame ->
            { model | world = World.simulate (seconds (1 / 60)) model.world }

        Resize width height ->
            { model | width = width, height = height }

        -- 書き直し箇所その2 ここをelm-physicsのLack.elのupdate関数を参考に書き換える
        KeyDown keyRay ->
            case model.maybeRaycastResult of
                Just raycastResult ->
                    let
                        worldPoint =
                            Point3d.placeIn
                                (Body.frame raycastResult.body)
                                raycastResult.point

                        plane =
                            Plane3d.through
                                worldPoint
                                (Viewpoint3d.viewDirection (Camera3d.viewpoint camera))
                    in
                    { model
                        | world =
                            World.update
                                (\body ->
                                    if (Body.data body).id == Key then
                                        case Axis3d.intersectionWithPlane plane keyRay of
                                            Just intersection ->
                                                Body.moveTo intersection body

                                            Nothing ->
                                                body

                                    else
                                        body
                                )
                                model.world
                    }

                Nothing ->
                    model

        KeyUp ->
            { model
                | maybeRaycastResult = Nothing
                , world =
                    World.keepIf
                        (\body -> (Body.data body).id /= Key)
                        model.world
            }

        Restart ->
            { model | world=initialWorld }

-- SUBSCRIPTISONS
subscriptions : Model -> Sub Msg
subscriptions _ =
    Sub.batch
        [ Browser.Events.onResize
            (\width height ->
                Resize (pixels (toFloat width)) (pixels (toFloat height))
            )
        , Browser.Events.onAnimationFrame (\_ -> AnimationFrame)
        ]

-- VIEW

view : Model -> Html Msg
view model =
    let
        entities =
            List.map
                (\body ->
                    Scene3d.placeIn
                        (frame body)
                        (data body).entity
                )
                (World.bodies model.world)
    in
    Html.div [ ]
            [ Scene3d.sunny
                { upDirection = Direction3d.z
                , sunlightDirection = Direction3d.xyZ (Angle.degrees 135) (Angle.degrees -60)
                , shadows = True
                , camera = camera
                , dimensions =
                    ( Pixels.int (round (Pixels.toFloat model.width))
                    , Pixels.int (round (Pixels.toFloat model.height))
                    )
                , background = Scene3d.transparentBackground
                , clipDepth = Length.meters 0.1
                , entities = entities
                }
            ]

-- RENDERING

camera : Camera3d Meters WorldCoordinates
camera =
    -- 俯瞰する類のカメラかな?
    -- the model
    Camera3d.perspective
        { viewpoint =
            Viewpoint3d.lookAt
                { eyePoint = Point3d.meters 3 4 2
                , focalPoint = Point3d.meters -0.5 -0.5 0
                , upDirection = Direction3d.positiveZ
                }
        , verticalFieldOfView = Angle.degrees 30
        }


```

<button title="Copy to Clipboard" class="sc-htpNat dmiDU"><svg viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg></button>

Is there any good solution?


HostSubmitted(+1)

shoshinsha, hello and sorry for the late reply!

I hope that I understood your question correctly. In order to integrate Elm with keyboard events, you need to use Browser Events and write a decoder from the event to your message type. So, if you want to handle arrow keys, the following decoder should work well for games

Let me know if this was helpful or if you have any further questions!

hi unsoundscapes and sorry for the delay in replying.

Thank you. I would like to develop with these in mind.

I will ask questions again when I come across something I don't understand.