Skip to content

Commit

Permalink
Add screen pos to char rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
samipourquoi committed Feb 7, 2021
1 parent d9b7e1a commit e847f7b
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 14 deletions.
3 changes: 2 additions & 1 deletion donut-hs.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ build-type: Simple
executable donut-hs
main-is: Main.hs
other-modules: Data.Vector
build-depends: base >=4.14 && <4.15
build-depends: base >=4.14 && <4.15,
terminal-size
hs-source-dirs: src
default-language: Haskell2010
7 changes: 5 additions & 2 deletions src/Data/Vector.hs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
module Data.Vector
( Vector(Vector) ) where
( Vector(..) ) where

data Vector a = Vector a a a
deriving (Show, Eq)

instance (Num a) => Num (Vector a) where
(Vector x1 y1 z1) + (Vector x2 y2 z2) = Vector (x1+x2) (y1+y2) (z1+z2)
(*) = undefined
(Vector x1 y1 z1) * (Vector x2 y2 z2) = Vector (x1*x2) (y1*y2) (z1*z2)
abs = undefined
signum = undefined
fromInteger = undefined
negate = undefined

instance Functor Vector where
fmap f (Vector x y z) = Vector (f x) (f y) (f z)
67 changes: 56 additions & 11 deletions src/Main.hs
Original file line number Diff line number Diff line change
@@ -1,22 +1,67 @@
module Main where

import Data.Vector
import System.Console.Terminal.Size

_r :: Float
_r = 1.0
_R :: Float
_R = 2.0
type ScreenPos = (Int, Int)

drawCircle :: Vector Float -> [Vector Float]
drawCircle center = map ((+) center . vradius) [0,0.1..2*pi]
where
type Grid = [[Char]]

k :: Float
k = 1

-- | A torus is essentially a circle cloned around a central point;
-- we thus define r as being the radius of the center,
r :: Float
r = 5
-- and r' a being the distance between the center of the
-- circle and the central point of the torus.
r' :: Float
r' = 25

-- | Generates every point of a circle of radius r and
-- center c.
generateCircle :: Vector Float -> [Vector Float]
generateCircle c = map ((+) c . vradius) [0.0,0.05..2*pi]
where
-- | Generates a vector corresponding to the
-- radius, rotated by the given angle theta.
-- It is centered at point (0,0,0); we need to add that
-- vector the vector c.
vradius :: Float -> Vector Float
vradius theta = Vector (_r * cos theta) (_r * sin theta) 0
vradius theta = Vector (r * cos theta) (r * sin theta) 0

-- | Projects a vector to a point on the screen
project :: Vector Float -> ScreenPos
project v@(Vector _ _ z) = pair . fmap (round . (* (k/z))) $ v
where pair (Vector x y _) = (x, y)

render :: [[Char]]
render = ["hello", "world"]
-- | Creates our final render made out of char,
-- based on screen coordinates that must get rendered.
renderScreenCoordinates :: [ScreenPos] -> Grid
renderScreenCoordinates coordinates =
map (concatMap (\cell -> if mustRender cell then ".." else " ")) gridCoordinates
where
gridCoordinates :: [[ScreenPos]]
gridCoordinates = [
[ (x, y) | x <- take 40 [0..] ]
| y <- take 24 [0..] ]

mustRender :: ScreenPos -> Bool
mustRender pos = pos `elem` coordinates

-- | Starts the rendering process.
render :: Window Int -> [[Char]]
render win@(Window w h) = coordinates
where
coordinates = renderScreenCoordinates $ map project $ generateCircle (Vector r' 5 1)

main :: IO ()
main = do
let screen = unlines render
window <- size
window <- case window of
Just a -> return a
Nothing -> return $ Window 80 24

let screen = unlines $ render window
putStr screen

0 comments on commit e847f7b

Please sign in to comment.