Add menu option to start new game from seed, uses system clipboard

This commit is contained in:
2021-12-09 14:36:26 +00:00
parent eeda4f3e39
commit 24a0cc289f
13 changed files with 101 additions and 54 deletions
+6 -4
View File
@@ -3,7 +3,9 @@ module Main
) where ) where
import Loop import Loop
import Dodge.Data import Dodge.Data
import Dodge.LevelGen import Dodge.StartNewGame
import Dodge.Initialisation
--import Dodge.LevelGen
import Dodge.Update import Dodge.Update
import Dodge.Event import Dodge.Event
import Dodge.Render import Dodge.Render
@@ -55,9 +57,9 @@ firstWorldLoad theConfig = do
SDL.cursorVisible $= False SDL.cursorVisible $= False
theKeyConfig <- loadKeyConfig theKeyConfig <- loadKeyConfig
pdata <- doPreload >>= applyWorldConfig theConfig pdata <- doPreload >>= applyWorldConfig theConfig
w <- generateWorldFromSeed 0 -- w <- generateWorldFromSeed 0
return $ Universe return $ startNewGame $ Universe
{_uvWorld = w {_uvWorld = initialWorld
,_config = theConfig ,_config = theConfig
,_preloadData = pdata ,_preloadData = pdata
,_menuLayers = [] ,_menuLayers = []
+1
View File
@@ -53,6 +53,7 @@ dependencies:
- repa - repa
- monad-parallel - monad-parallel
- parallel - parallel
- Clipboard
library: library:
source-dirs: src source-dirs: src
+17 -3
View File
@@ -1,6 +1,20 @@
module Dodge.Creature.HandPos where module Dodge.Creature.HandPos where
import Dodge.Data import Dodge.Data
import Geometry --import Geometry
import Control.Lens
import Data.Maybe
crHandPos :: Creature -> Point3 -- the position of a weapon handle
crHandPos _ = V3 0 0 20 aimingWeaponHandlePos :: Creature -> Item -> Float
aimingWeaponHandlePos cr it = case it ^? itUse. useAim . aimStance of
Just TwoHandTwist -> -5
Just OneHand -> 14
Just TwoHandFlat -> 1.2 * _crRad cr
Just LeaveHolstered -> 0
Nothing -> 0
aimingWeaponZeroPos :: Creature -> Item -> Float
aimingWeaponZeroPos cr it = aimingWeaponHandlePos cr it
- fromMaybe 0 (it ^? itDimension . dimPortage . handlePos)
aimingMuzzlePos :: Creature -> Item -> Float
aimingMuzzlePos cr it = aimingWeaponZeroPos cr it
+ fromMaybe 0 (it ^? itDimension . dimPortage . muzPos)
+2 -2
View File
@@ -1,7 +1,7 @@
module Dodge.Initialisation where module Dodge.Initialisation where
import Dodge.Default.World import Dodge.Default.World
import Dodge.Base import Dodge.Base
import Dodge.Save --import Dodge.Save
import Dodge.Data import Dodge.Data
import Dodge.Creature import Dodge.Creature
--import Dodge.Story --import Dodge.Story
@@ -28,7 +28,7 @@ initialWorld = defaultWorld
, _mousePos = V2 0 0 , _mousePos = V2 0 0
, _testString = testStringInit , _testString = testStringInit
, _yourID = 0 , _yourID = 0
, _sideEffects = return .saveWorldInEmptySlot LevelStartSlot , _sideEffects = return
, _worldEvents = soundStart BackgroundSound (V2 0 0) foamSprayFadeOutS Nothing , _worldEvents = soundStart BackgroundSound (V2 0 0) foamSprayFadeOutS Nothing
. foldr ((.) . makeStartCloudAt) id [V3 x y 5 | x <- [-5,-4..5] , y <- [-5,-4..5]] . foldr ((.) . makeStartCloudAt) id [V3 x y 5 | x <- [-5,-4..5] , y <- [-5,-4..5]]
, _pressPlates = IM.empty , _pressPlates = IM.empty
+4 -9
View File
@@ -4,6 +4,7 @@ import Dodge.Data
--import Picture --import Picture
--import Shape --import Shape
import ShapePicture import ShapePicture
import Dodge.Creature.HandPos
import qualified Data.IntMap.Strict as IM import qualified Data.IntMap.Strict as IM
import Control.Lens import Control.Lens
@@ -44,12 +45,8 @@ pictureWeaponOnAimItem
-> Int -- ^ Position of item in inventory -> Int -- ^ Position of item in inventory
-> SPic -> SPic
pictureWeaponOnAimItem p' cr posInInv pictureWeaponOnAimItem p' cr posInInv
| isSelected && _posture (_crStance cr) == Aiming && isTwisting | isSelected && _posture (_crStance cr) == Aiming =
= shoulderD twistWep shoulderD $ translateSPf (aimingWeaponZeroPos cr theIt) 0 p'
| isSelected && _posture (_crStance cr) == Aiming && isOneHand
= shoulderD oneHandWep
| isSelected && _posture (_crStance cr) == Aiming && isTwoHandFlat
= shoulderD drawnWep
| isSelected && isTwoHandFlat | isSelected && isTwoHandFlat
= handD holsteredTwoFlat = handD holsteredTwoFlat
| isSelected && isOneHand | isSelected && isOneHand
@@ -61,9 +58,7 @@ pictureWeaponOnAimItem p' cr posInInv
shoulderD = translateSPz 18 shoulderD = translateSPz 18
handD = translateSPz 15 handD = translateSPz 15
isSelected = _crInvSel cr == posInInv isSelected = _crInvSel cr == posInInv
drawnWep = translateSPf (1.2 * _crRad cr) 0 p
twistWep = translateSPf (-5) 0 p twistWep = translateSPf (-5) 0 p
oneHandWep = translateSPf 14 0 p
holsteredWep = translateSPf (_crRad cr) 0 holsteredWep = translateSPf (_crRad cr) 0
(rotateSP (strideRot cr + 1.2) (translateSPf (-5) 0 twistWep)) (rotateSP (strideRot cr + 1.2) (translateSPf (-5) 0 twistWep))
holsteredTwoFlat = translateSPf (_crRad cr) 0 (rotateSP (twoFlatHRot cr) p) holsteredTwoFlat = translateSPf (_crRad cr) 0 (rotateSP (twoFlatHRot cr) p)
@@ -76,13 +71,13 @@ pictureWeaponOnAimItem p' cr posInInv
p = fromMaybe p' $ do p = fromMaybe p' $ do
x <- theIt ^? itDimension . dimPortage . handlePos x <- theIt ^? itDimension . dimPortage . handlePos
return $translateSPf (-x) 0 p' return $translateSPf (-x) 0 p'
isTwisting = theIt ^? itUseAimStance == Just TwoHandTwist
isOneHand = theIt ^? itUseAimStance == Just OneHand isOneHand = theIt ^? itUseAimStance == Just OneHand
isTwoHandFlat = theIt ^? itUseAimStance == Just TwoHandFlat isTwoHandFlat = theIt ^? itUseAimStance == Just TwoHandFlat
itUseAimStance = itUse . useAim . aimStance itUseAimStance = itUse . useAim . aimStance
f i = 0.1 * fromIntegral (sLen - i) / fromIntegral sLen f i = 0.1 * fromIntegral (sLen - i) / fromIntegral sLen
sLen = _strideLength $ _crStance cr sLen = _strideLength $ _crStance cr
strideRot :: Creature -> Float strideRot :: Creature -> Float
strideRot cr = case cr ^? crStance . carriage of strideRot cr = case cr ^? crStance . carriage of
Just (Walking x LeftForward) -> f x Just (Walking x LeftForward) -> f x
+4 -2
View File
@@ -8,6 +8,7 @@ module Dodge.Item.Weapon.AmmoParams
) where ) where
import Dodge.Data import Dodge.Data
import Dodge.Particle.Bullet.Spawn import Dodge.Particle.Bullet.Spawn
import Dodge.Creature.HandPos
import Geometry import Geometry
import LensHelp import LensHelp
@@ -33,14 +34,15 @@ defaultAimParams = AimParams
} }
useAmmoParams :: Item -> Creature -> World -> World useAmmoParams :: Item -> Creature -> World -> World
useAmmoParams it = withVelWthHiteff useAmmoParams it cr = withVelWthHiteff
(muzvel *.* _amBulVel b) (muzvel *.* _amBulVel b)
(_rifling $ _itParams it) (_rifling $ _itParams it)
(_amBulWth b) (_amBulWth b)
muzlength muzlength
(_amBulEff b) (_amBulEff b)
cr
where where
muzlength = 20 muzlength = aimingMuzzlePos cr it
muzvel = _muzVel $ _itParams it muzvel = _muzVel $ _itParams it
b = _aoType $ _itConsumption it b = _aoType $ _itConsumption it
+1 -1
View File
@@ -67,7 +67,7 @@ bangCane = defaultGun
, _dimCenter = V3 5 0 0 , _dimCenter = V3 5 0 0
, _dimPortage = HeldItem , _dimPortage = HeldItem
{_handlePos = 5 {_handlePos = 5
,_muzPos = 20 ,_muzPos = 15
} }
, _dimSPic = \it -> noPic $ baseCaneShape , _dimSPic = \it -> noPic $ baseCaneShape
<> makeSingleClipAt (V3 5 0 3) it <> makeSingleClipAt (V3 5 0 3) it
+2 -1
View File
@@ -3,6 +3,7 @@
module Dodge.LevelGen where module Dodge.LevelGen where
import Dodge.Data import Dodge.Data
import Dodge.Floor import Dodge.Floor
import Dodge.Save
import Dodge.Layout import Dodge.Layout
import Dodge.Initialisation import Dodge.Initialisation
--import Dodge.RandomHelp --import Dodge.RandomHelp
@@ -19,7 +20,7 @@ import qualified Data.IntMap.Strict as IM
generateWorldFromSeed :: Int -> IO World generateWorldFromSeed :: Int -> IO World
generateWorldFromSeed i = do generateWorldFromSeed i = do
roomList <- layoutLevelFromSeed 0 i roomList <- layoutLevelFromSeed 0 i
return $ _gWorld $ generateLevelFromRoomList roomList return $ saveLevelStartSlot $ _gWorld $ generateLevelFromRoomList roomList
initialWorld{_randGen=mkStdGen i} initialWorld{_randGen=mkStdGen i}
layoutLevelFromSeed :: Int -> Int -> IO (IM.IntMap Room) layoutLevelFromSeed :: Int -> Int -> IO (IM.IntMap Room)
+4 -2
View File
@@ -16,8 +16,9 @@ curveLeftField mg pt = case pt of
curveAroundField :: Magnet -> Particle -> Particle curveAroundField :: Magnet -> Particle -> Particle
curveAroundField mg pt = case pt of curveAroundField mg pt = case pt of
BulletPt{} | dist btpos mgpos < 500 -> pt & btVel' %~ rotateToCircle BulletPt{} | thedist < 400 -> pt & btVel' %~ rotateToCircle
where where
thedist = dist btpos mgpos
mgpos = _mgPos mg mgpos = _mgPos mg
btpos = head $ _btTrail' pt btpos = head $ _btTrail' pt
rotateToCircle vel rotateToCircle vel
@@ -25,5 +26,6 @@ curveAroundField mg pt = case pt of
|| (isRHS mgpos btpos (btpos +.+ vel) && isLHS mgpos btpos (mgpos +.+ vNormal vel) ) || (isRHS mgpos btpos (btpos +.+ vel) && isLHS mgpos btpos (mgpos +.+ vNormal vel) )
= rotateV rot vel = rotateV rot vel
| otherwise = rotateV (negate rot) vel | otherwise = rotateV (negate rot) vel
rot = 0.5 rot | thedist < 100 = 0.5
| otherwise = 0.5 - ((thedist - 100) / 600)
_ -> pt _ -> pt
+27 -24
View File
@@ -5,22 +5,22 @@ module Dodge.Menu
) where ) where
import LensHelp import LensHelp
import Dodge.Menu.OptionType import Dodge.Menu.OptionType
import Dodge.StartNewGame
import Dodge.Menu.PushPop import Dodge.Menu.PushPop
import Dodge.Data import Dodge.Data
import Dodge.PreloadData import Dodge.PreloadData
import Dodge.Save import Dodge.Save
import Dodge.Config.Update import Dodge.Config.Update
import SDL
--import SDL.Internal.Numbered --import SDL.Internal.Numbered
--import Preload.Update --import Preload.Update
import Dodge.SoundLogic import Dodge.SoundLogic
import Dodge.LevelGen --import Dodge.LevelGen
import Text.Read
import SDL
import System.Clipboard
--import Control.Lens --import Control.Lens
import System.Random --import System.Random
pauseMenu :: ScreenLayer
pauseMenu = slTitleOptionsEff "PAUSED" pauseMenuOptions (return . unpause)
slTitleOptionsEff :: String -> [MenuOption] -> (Universe -> IO (Maybe Universe)) -> ScreenLayer slTitleOptionsEff :: String -> [MenuOption] -> (Universe -> IO (Maybe Universe)) -> ScreenLayer
slTitleOptionsEff title ops eff = OptionScreen slTitleOptionsEff title ops eff = OptionScreen
@@ -29,15 +29,34 @@ slTitleOptionsEff title ops eff = OptionScreen
, _scDefaultEff = eff , _scDefaultEff = eff
, _scOptionFlag = NormalOptions , _scOptionFlag = NormalOptions
} }
pauseMenu :: ScreenLayer
pauseMenu = slTitleOptionsEff "PAUSED" pauseMenuOptions (return . unpause)
pauseMenuOptions :: [MenuOption] pauseMenuOptions :: [MenuOption]
pauseMenuOptions = pauseMenuOptions =
[ Toggle ScancodeN (return . startNewGame) (const "NEW LEVEL") [ Toggle ScancodeN (return . Just . startNewGame) (const "NEW LEVEL")
, Toggle ScancodeR (return . Just . loadSaveSlot LevelStartSlot) (const "RESTART") , Toggle ScancodeR (return . Just . loadSaveSlot LevelStartSlot) (const "RESTART")
, Toggle ScancodeS (pushScreen $ seedStartMenu "START FROM SEED") (const "START FROM SEED")
, Toggle ScancodeO (pushScreen optionMenu ) (const "OPTIONS") , Toggle ScancodeO (pushScreen optionMenu ) (const "OPTIONS")
, Toggle ScancodeC (pushScreen displayControls) (const "CONTROLS") , Toggle ScancodeC (pushScreen displayControls) (const "CONTROLS")
, InvisibleToggle ScancodeEscape (return . const Nothing) , InvisibleToggle ScancodeEscape (return . const Nothing)
] ]
seedStartMenu :: String -> ScreenLayer
seedStartMenu str = slTitleOptionsEff str seedStartOptions popScreen
seedStartOptions :: [MenuOption]
seedStartOptions =
[ Toggle ScancodeP trySeedFromClipboard (const "PASTE NUMBER FROM CLIPBOARD")
-- , Toggle ScancodeI (return . Just . loadSaveSlot LevelStartSlot) (const "INSERT NUMBER")
]
trySeedFromClipboard :: Universe -> IO (Maybe Universe)
trySeedFromClipboard u = do
mcstr <- getClipboardString
case mcstr of
Nothing -> pushScreen (seedStartMenu "INPUT UNUSABLE") (u & menuLayers %~ tail)
Just str -> do
case readMaybe str of
Nothing -> pushScreen (seedStartMenu "INPUT UNUSABLE") (u & menuLayers %~ tail)
Just i -> return . Just $ startSeedGame i u
slTitleOptions :: String -> [MenuOption] -> ScreenLayer slTitleOptions :: String -> [MenuOption] -> ScreenLayer
slTitleOptions title ops = slTitleOptionsEff title ops (popScreen . writeConfig) slTitleOptions title ops = slTitleOptionsEff title ops (popScreen . writeConfig)
@@ -122,22 +141,6 @@ gameOverMenu = OptionScreen
, _scOptionFlag = GameOverOptions , _scOptionFlag = GameOverOptions
} }
--startNewGame' :: Universe -> IO (Maybe Universe)
--startNewGame' u = do
-- w <- generateWorldFromSeed i
-- return $ Just (u & uvWorld .~ w)
-- where
-- i = fst $ random (_randGen (_uvWorld u))
startNewGame :: Universe -> Maybe Universe
startNewGame u = Just $ u
& menuLayers .~ [WaitScreen (const "GENERATING...") 1]
& uvWorld . sideEffects .~ \_ -> do
w <- generateWorldFromSeed i
return (u & menuLayers .~ [] & uvWorld .~ w)
where
i = fst $ random (_randGen (_uvWorld u))
-- | hacky -- | hacky
scodeToChar :: Scancode -> Char scodeToChar :: Scancode -> Char
scodeToChar = toEnum . (+ 61) . fromIntegral . unwrapScancode scodeToChar = toEnum . (+ 61) . fromIntegral . unwrapScancode
+8 -5
View File
@@ -8,17 +8,17 @@ import Dodge.Wall.Delete
import Dodge.WorldEvent.Explosion import Dodge.WorldEvent.Explosion
import Dodge.Item.Weapon.BatteryGuns import Dodge.Item.Weapon.BatteryGuns
import Dodge.Item.Weapon.BulletGun.Cane import Dodge.Item.Weapon.BulletGun.Cane
import Dodge.SoundLogic.LoadSound --import Dodge.SoundLogic.LoadSound
import Dodge.SoundLogic --import Dodge.SoundLogic
import Dodge.Item.Draw import Dodge.Item.Draw
import Geometry import Geometry
import ShapePicture import ShapePicture
import Shape import Shape
import Dodge.Base import Dodge.Base
import Dodge.Base.Collide import Dodge.Base.Collide
import LensHelp
import Data.List import Data.List
import Control.Lens
import qualified Data.IntMap.Strict as IM import qualified Data.IntMap.Strict as IM
putLasTurret :: Float -> Placement putLasTurret :: Float -> Placement
@@ -52,10 +52,13 @@ updateTurret rotSpeed mc w
| elecDam < 10 = updateFiringStatus . doTurn | elecDam < 10 = updateFiringStatus . doTurn
| otherwise = id | otherwise = id
-- TODO make this use the same function as the lasgun -- TODO make this use the same function as the lasgun
it = _tuWeapon (_mcType mc)
maybeFire maybeFire
| _tuFireTime (_mcType mc) > 0 | _tuFireTime (_mcType mc) > 0
= ( particles %~ (makeLaserAt 5 (mcpos + 15 *.* unitVectorAtAngle mcdir) mcdir :) ) -- massive hack
. soundContinue (MachineSound mcid) mcpos tone440sawtoothquietS (Just 1) = _rUse (_itUse it) it (defaultCreature {_crPos = mcpos,_crDir = mcdir})
-- = ( particles .:~ makeLaserAt 5 (mcpos + 15 *.* unitVectorAtAngle mcdir) mcdir )
-- . soundContinue (MachineSound mcid) mcpos tone440sawtoothquietS (Just 1)
| otherwise = id | otherwise = id
mcid = _mcID mc mcid = _mcID mc
ypos = _crPos $ you w ypos = _crPos $ you w
+7 -1
View File
@@ -2,6 +2,7 @@ module Dodge.Save
( saveWorldInEmptySlot ( saveWorldInEmptySlot
, loadSaveSlot , loadSaveSlot
, doQuicksave , doQuicksave
, saveLevelStartSlot
) where ) where
import Dodge.Data import Dodge.Data
@@ -16,7 +17,7 @@ saveWorldInEmptySlot slot w = case M.lookup slot $ _savedWorlds w of
_ -> w _ -> w
saveWorldInSlot :: SaveSlot -> Universe -> Universe saveWorldInSlot :: SaveSlot -> Universe -> Universe
saveWorldInSlot slot w = w & savedWorlds %~ M.insert slot (clearKeys (_uvWorld w)) saveWorldInSlot slot u = u & savedWorlds %~ M.insert slot (clearKeys (_uvWorld u))
loadSaveSlot :: SaveSlot -> Universe -> Universe loadSaveSlot :: SaveSlot -> Universe -> Universe
loadSaveSlot slot u = maybe u loadSaveSlot slot u = maybe u
@@ -28,3 +29,8 @@ doQuicksave = saveWorldInSlot QuicksaveSlot
clearKeys :: World -> World clearKeys :: World -> World
clearKeys = (keys .~ S.empty) . (mouseButtons .~ S.empty) clearKeys = (keys .~ S.empty) . (mouseButtons .~ S.empty)
saveLevelStartSlot :: World -> World
--saveLevelStartSlot = id
saveLevelStartSlot = sideEffects %~ (fmap (saveWorldInSlot LevelStartSlot) . )
--saveLevelStartSlot = sideEffects %~ (fmap (undefined) . )
+18
View File
@@ -0,0 +1,18 @@
module Dodge.StartNewGame where
import Dodge.Data
import Dodge.LevelGen
import Control.Lens
import System.Random
startNewGame :: Universe -> Universe
startNewGame u = startSeedGame i u
where
i = fst $ random (_randGen (_uvWorld u))
startSeedGame :: Int -> Universe -> Universe
startSeedGame i u = u
& menuLayers .~ [WaitScreen (const "GENERATING...") 1]
& uvWorld . sideEffects .~ \_ -> do
w <- generateWorldFromSeed i
return $ u & menuLayers .~ [] & uvWorld .~ w
& savedWorlds . at LevelStartSlot ?~ w