packages feed

mischief-render-0.1.0.0: examples/start/Start.hs

{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE OverloadedStrings #-}

module Main where

import Control.Monad (void)
import Data.Default
import Data.Text (Text)
import Mischief.Animation
import Mischief.Assets
import Mischief.ECS
import Mischief.ECS.Time qualified as Time
import Mischief.Input
import Mischief.Input.Keys qualified as Keys
import Mischief.Math hiding (qd)
import Mischief.Math.Transform qualified as Transform
import Mischief.Render
import MyMaterial (MyColor (..), MyMaterial)

main :: IO ()
main = do
  app <- newApp
  setAssetSource "assets/" app
  addPlugin @MainPlugin app
  runApp app

data MainPlugin

instance Plugin MainPlugin where
  init = do
    systems setup
      & schedule @Startup

    systems (movement, maintainBuffer @MyColor)
      & schedule @RenderPrepare

    systems (renderSortedMaterial @MyMaterial def getY)
      & schedule @RenderUpdate

  deps = [dep @RenderPlugin, dep @InputPlugin, dep @TimePlugin, dep @AnimationPlugin, dep @FileWatcherPlugin]

data Player = Player deriving (Component)

getY :: Entity -> Query System Float
getY entity = do
  Transform {translation} <- [q|entity. Transform|]
  pure (-translation.y)

setup :: System ()
setup = do
  window <- spawn Window
  void $ spawn (Camera, Rel OutputTo window)

  e <-
    spawn
      ( Animator MyAnimator,
        Anchor $ V2 0.5 0.9,
        WithMaterial @MyMaterial,
        def {translation = V3 (-60) 0 0},
        MyColor @CPU (V3 1 1 0),
        Player
      )

  shift (ChangeCharacter Pink) e

  e <-
    spawn
      ( Animator MyAnimator,
        Anchor $ V2 0.5 0.9,
        WithMaterial @MyMaterial,
        MyColor @CPU (V3 0 1 1),
        def {translation = V3 60 0 0}
      )

  shift (ChangeCharacter Green) e

movement :: System ()
movement = do
  Just keys <- res @Keys
  Just (player, transform) <- single [q|Entity, Transform / With Player|]

  delta <- Time.delta
  let speed = 150

  let dirX =
        if
          | Keys.pressed keys Keys.A -> -1
          | Keys.pressed keys Keys.D -> 1
          | otherwise -> 0

  let dirY =
        if
          | Keys.pressed keys Keys.S -> -1
          | Keys.pressed keys Keys.W -> 1
          | otherwise -> 0

  let dir = normalize $ V3 dirX dirY 0

  let walk = norm dir > 0
  input @MyAnimator (\i -> i {walk}) player

  let flip = dir.x < 0
  insert (SpriteFlip {x = False, y = flip}) player

  insert (Transform.move (dir ^* delta * speed) transform) player

data MyAnimator = MyAnimator

data Character = Green | Pink

charName :: Character -> Text
charName Green = "green"
charName Pink = "pink"

data AnimationType = Idle | Walk

instance AnimatorTag MyAnimator where
  data Input MyAnimator = Input {walk :: Bool} deriving (Generic, Default)
  data Shift MyAnimator = ChangeCharacter Character
  data State MyAnimator = Start | CharacterAnimation Character AnimationType

  animation (CharacterAnimation c Idle) = selAnim "animations.kdl" (charName c <> "_idle")
  animation (CharacterAnimation c Walk) = selAnim "animations.kdl" (charName c <> "_walk")
  animation Start = noAnimation

  transition (CharacterAnimation c Idle) Input {walk = True} _ _ = Just (CharacterAnimation c Walk)
  transition (CharacterAnimation c Walk) Input {walk = False} _ _ = Just (CharacterAnimation c Idle)
  transition Start _ (Just (ChangeCharacter c)) _ = Just (CharacterAnimation c Idle)
  transition _ _ _ _ = Nothing

  start = Start