Skip to content

Commit c7b1a3a

Browse files
committed
feat: update to latest aztecs packages and refactor
1 parent bc7f861 commit c7b1a3a

12 files changed

Lines changed: 274 additions & 58 deletions

.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
* text=auto
22
*.hs text eol=lf
3+
*.txt text eol=lf
34
*.jpg binary
45
*.png binary
6+
*.ttf binary

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@ Examples can be run with `cabal run {example}`, for instance `cabal run ecs`
1515
- [`pong`](https://github.com/aztecs-hs/examples/blob/main/src/Pong.hs): Full pong game implementation
1616
- [`sprite`](https://github.com/aztecs-hs/examples/blob/main/src/Sprite.hs): Sprite rendering
1717
- [`spritesheet`](https://github.com/aztecs-hs/examples/blob/main/src/Sprite.hs): Animated sprite sheet rendering
18+
- [`text`](https://github.com/aztecs-hs/examples/blob/main/src/Text.hs): Text rendering with OpenGL
1819
- [`window`](https://github.com/aztecs-hs/examples/blob/main/src/Window.hs): GLFW window example
1920

2021
## Assets
2122

2223
- `IDLE.png`: [Samurai](https://xzany.itch.io/samurai-2d-pixel-art) by mattz_21
24+
- `Montserrat-VariableFont_wght.ttf`: [Montserrat](https://github.com/JulietaUla/Montserrat) by [JulietaUla](https://github.com/JulietaUla)
672 KB
Binary file not shown.

assets/OFL.txt

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
Copyright 2024 The Montserrat.Git Project Authors (https://github.com/JulietaUla/Montserrat.git)
2+
3+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
4+
This license is copied below, and is also available with a FAQ at:
5+
https://openfontlicense.org
6+
7+
8+
-----------------------------------------------------------
9+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10+
-----------------------------------------------------------
11+
12+
PREAMBLE
13+
The goals of the Open Font License (OFL) are to stimulate worldwide
14+
development of collaborative font projects, to support the font creation
15+
efforts of academic and linguistic communities, and to provide a free and
16+
open framework in which fonts may be shared and improved in partnership
17+
with others.
18+
19+
The OFL allows the licensed fonts to be used, studied, modified and
20+
redistributed freely as long as they are not sold by themselves. The
21+
fonts, including any derivative works, can be bundled, embedded,
22+
redistributed and/or sold with any software provided that any reserved
23+
names are not used by derivative works. The fonts and derivatives,
24+
however, cannot be released under any other type of license. The
25+
requirement for fonts to remain under this license does not apply
26+
to any document created using the fonts or their derivatives.
27+
28+
DEFINITIONS
29+
"Font Software" refers to the set of files released by the Copyright
30+
Holder(s) under this license and clearly marked as such. This may
31+
include source files, build scripts and documentation.
32+
33+
"Reserved Font Name" refers to any names specified as such after the
34+
copyright statement(s).
35+
36+
"Original Version" refers to the collection of Font Software components as
37+
distributed by the Copyright Holder(s).
38+
39+
"Modified Version" refers to any derivative made by adding to, deleting,
40+
or substituting -- in part or in whole -- any of the components of the
41+
Original Version, by changing formats or by porting the Font Software to a
42+
new environment.
43+
44+
"Author" refers to any designer, engineer, programmer, technical
45+
writer or other person who contributed to the Font Software.
46+
47+
PERMISSION & CONDITIONS
48+
Permission is hereby granted, free of charge, to any person obtaining
49+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
50+
redistribute, and sell modified and unmodified copies of the Font
51+
Software, subject to the following conditions:
52+
53+
1) Neither the Font Software nor any of its individual components,
54+
in Original or Modified Versions, may be sold by itself.
55+
56+
2) Original or Modified Versions of the Font Software may be bundled,
57+
redistributed and/or sold with any software, provided that each copy
58+
contains the above copyright notice and this license. These can be
59+
included either as stand-alone text files, human-readable headers or
60+
in the appropriate machine-readable metadata fields within text or
61+
binary files as long as those fields can be easily viewed by the user.
62+
63+
3) No Modified Version of the Font Software may use the Reserved Font
64+
Name(s) unless explicit written permission is granted by the corresponding
65+
Copyright Holder. This restriction only applies to the primary font name as
66+
presented to the users.
67+
68+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69+
Software shall not be used to promote, endorse or advertise any
70+
Modified Version, except to acknowledge the contribution(s) of the
71+
Copyright Holder(s) and the Author(s) or with their explicit written
72+
permission.
73+
74+
5) The Font Software, modified or unmodified, in part or in whole,
75+
must be distributed entirely under this license, and must not be
76+
distributed under any other license. The requirement for fonts to
77+
remain under this license does not apply to any document created
78+
using the Font Software.
79+
80+
TERMINATION
81+
This license becomes null and void if any of the above conditions are
82+
not met.
83+
84+
DISCLAIMER
85+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93+
OTHER DEALINGS IN THE FONT SOFTWARE.

aztecs-examples.cabal

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ executable 2D
1313
build-depends:
1414
base,
1515
aztecs >=0.17.1 && <0.18,
16-
aztecs-gl >=0.2.1 && <0.3,
16+
aztecs-gl >=0.3 && <0.4,
1717
aztecs-glfw >=0.2 && <0.3
1818

1919
executable ecs
@@ -31,7 +31,7 @@ executable sprite
3131
build-depends:
3232
base,
3333
aztecs >=0.17.1 && <0.18,
34-
aztecs-gl >=0.2.1 && <0.3,
34+
aztecs-gl >=0.3 && <0.4,
3535
aztecs-glfw >=0.2 && <0.3
3636

3737
executable spritesheet
@@ -41,7 +41,7 @@ executable spritesheet
4141
build-depends:
4242
base,
4343
aztecs >=0.17.1 && <0.18,
44-
aztecs-gl >=0.2.1 && <0.3,
44+
aztecs-gl >=0.3 && <0.4,
4545
aztecs-glfw >=0.2 && <0.3,
4646
mtl,
4747
time
@@ -69,11 +69,23 @@ executable pong
6969
build-depends:
7070
base,
7171
aztecs >=0.17.1 && <0.18,
72-
aztecs-gl >=0.2.1 && <0.3,
72+
aztecs-gl >=0.3 && <0.4,
7373
aztecs-glfw >=0.2 && <0.3,
74+
aztecs-gl-text >=0.1 && <0.2,
7475
mtl,
7576
time
7677

78+
executable text
79+
main-is: src/Text.hs
80+
default-language: Haskell2010
81+
ghc-options: -Wall
82+
build-depends:
83+
base,
84+
aztecs >=0.17.1 && <0.18,
85+
aztecs-gl >=0.3 && <0.4,
86+
aztecs-glfw >=0.2 && <0.3,
87+
aztecs-gl-text >=0.1 && <0.2
88+
7789
executable window
7890
main-is: src/Window.hs
7991
default-language: Haskell2010

src/2D.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
module Main where
44

55
import Aztecs
6-
import Aztecs.GL
6+
import Aztecs.GL.D2
77
import Aztecs.GLFW
88
import Control.Monad.IO.Class
99
import System.IO
@@ -61,6 +61,7 @@ main = runAccess_ $ do
6161
<> bundle (color 1 0 1 1)
6262
<> bundle (Parent windowEntity)
6363

64+
-- Run
6465
runAccessGLFW $ do
6566
render
6667
mKeys <- lookup @_ @Keys windowEntity

src/Observers.hs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ run = do
2121

2222
-- Spawn observers that react to lifecycle events on the player's Health component
2323
_ <- spawn . bundle . observer @IO @(OnInsert Health) player $ \e (OnInsert h) ->
24-
observe "insert" e h
25-
_ <- spawn . bundle . observer @IO @(OnChange Health) player $ \e change ->
26-
liftIO . putStrLn $ "change " ++ show e ++ ": old=" ++ show (onChangeOld change) ++ ", new=" ++ show (onChangeNew change)
24+
go "insert" e h
25+
_ <- spawn . bundle . observer @IO @(OnChange Health) player $ \e (OnChange _ new) ->
26+
go "change" e new
2727
_ <- spawn . bundle . observer @IO @(OnRemove Health) player $ \e (OnRemove h) ->
28-
observe "remove" e h
28+
go "remove" e h
2929

3030
-- Trigger events by inserting, changing, and removing the Health component
3131
_ <- insert player . bundle $ Health 150
@@ -34,7 +34,7 @@ run = do
3434

3535
return ()
3636
where
37-
observe s e h = liftIO . putStrLn $ s ++ " " ++ show e ++ ": " ++ show h
37+
go s e h = liftIO . putStrLn $ s ++ " " ++ show e ++ ": " ++ show h
3838

3939
main :: IO ()
4040
main = runAccess_ run

src/Pong.hs

Lines changed: 71 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,17 @@
66
module Main where
77

88
import Aztecs
9-
import Aztecs.GL
9+
import Aztecs.GL.D2
10+
import Aztecs.GL.Text
1011
import Aztecs.GLFW
1112
import Control.Monad
1213
import Control.Monad.IO.Class
1314
import Control.Monad.State.Strict
1415
import Data.Time.Clock
15-
import System.IO
1616
import Prelude hiding (lookup)
1717

18+
-- Configuration options
19+
1820
windowW, windowH :: Int
1921
windowW = 800
2022
windowH = 600
@@ -36,9 +38,10 @@ ballInitSpeedY = 200
3638
paddleMargin :: Float
3739
paddleMargin = 40
3840

39-
newtype GameState = GameState {gsLastTime :: UTCTime}
40-
deriving (Show)
41+
-- Current game state
42+
newtype GameState = GameState {lastTime :: UTCTime}
4143

44+
-- Game monad
4245
type GameM = StateT GameState IO
4346

4447
-- Paddle component
@@ -58,12 +61,12 @@ instance (Monad m) => Component m Ball
5861
main :: IO ()
5962
main = do
6063
now <- getCurrentTime
61-
let initialState = GameState {gsLastTime = now}
62-
(_, _) <- runStateT (runAccess_ setupAndRun) initialState
64+
let initialState = GameState {lastTime = now}
65+
(_, _) <- runStateT (runAccess_ run) initialState
6366
putStrLn "Game ended!"
6467

65-
setupAndRun :: Access GameM ()
66-
setupAndRun = do
68+
run :: Access GameM ()
69+
run = do
6770
-- Spawn the window
6871
windowEntity <-
6972
spawn $
@@ -106,26 +109,59 @@ setupAndRun = do
106109
<> bundle (Parent windowEntity)
107110
<> bundle (Ball ballInitSpeedX ballInitSpeedY)
108111

112+
-- Spawn font and score labels
113+
font <- spawn . bundle $ Font "assets/Montserrat-VariableFont_wght.ttf"
114+
115+
leftScoreLabelE <-
116+
spawn $
117+
bundle (Label "0" font defaultLabelStyle {labelFontSize = 48, labelColor = V4 1 1 1 1})
118+
<> bundle (transform2d {transformTranslation = V2 (round (centerX - 60)) (round (fromIntegral windowH - 50 :: Float))} :: Transform2D)
119+
<> bundle (Parent windowEntity)
120+
121+
rightScoreLabelE <-
122+
spawn $
123+
bundle (Label "0" font defaultLabelStyle {labelFontSize = 48, labelColor = V4 1 1 1 1})
124+
<> bundle (transform2d {transformTranslation = V2 (round (centerX + 40)) (round (fromIntegral windowH - 50 :: Float))} :: Transform2D)
125+
<> bundle (Parent windowEntity)
126+
109127
-- Run the game loop
110-
runAccessGLFW $ run windowEntity leftPaddleE rightPaddleE ballE
128+
let rs =
129+
Loop
130+
{ window = windowEntity,
131+
leftPaddle = leftPaddleE,
132+
rightPaddle = rightPaddleE,
133+
ball = ballE,
134+
leftScoreLabel = leftScoreLabelE,
135+
rightScoreLabel = rightScoreLabelE
136+
}
137+
runAccessGLFW $ loop rs
138+
139+
data Loop = Loop
140+
{ window :: EntityID,
141+
leftPaddle :: EntityID,
142+
rightPaddle :: EntityID,
143+
ball :: EntityID,
144+
leftScoreLabel :: EntityID,
145+
rightScoreLabel :: EntityID
146+
}
111147

112-
run :: EntityID -> EntityID -> EntityID -> EntityID -> Access GameM Bool
113-
run windowE leftE rightE ballE = do
148+
loop :: Loop -> Access GameM Bool
149+
loop rs = do
114150
now <- liftIO getCurrentTime
115-
lastTime <- lift $ gets gsLastTime
116-
let dt = realToFrac (diffUTCTime now lastTime) :: Float
151+
lt <- lift $ gets lastTime
152+
let dt = realToFrac (diffUTCTime now lt) :: Float
117153
dt' = min dt 0.1
118-
lift . modify' $ \gs -> gs {gsLastTime = now}
154+
lift . modify' $ \gs -> gs {lastTime = now}
119155

120-
mKeys <- lookup @_ @Keys windowE
156+
mKeys <- lookup @_ @Keys (window rs)
121157
case mKeys of
122158
Just keys -> do
123159
if keyJustPressed Key'Escape keys
124160
then return True
125161
else do
126-
updatePaddle leftE keys Key'W Key'S dt'
127-
updatePaddle rightE keys Key'Up Key'Down dt'
128-
updateBall dt' ballE leftE rightE
162+
updatePaddle (leftPaddle rs) keys Key'W Key'S dt'
163+
updatePaddle (rightPaddle rs) keys Key'Up Key'Down dt'
164+
updateBall dt' rs
129165
render
130166
return False
131167
Nothing -> do
@@ -149,18 +185,21 @@ updatePaddle paddleE keys upKey downKey dt = do
149185
$ bundle (t {transformTranslation = V2 x (round newY)} :: Transform2D)
150186
Nothing -> return ()
151187

152-
updateBall :: Float -> EntityID -> EntityID -> EntityID -> Access GameM ()
153-
updateBall dt ballE leftE rightE = do
188+
updateBall :: Float -> Loop -> Access GameM ()
189+
updateBall dt rs = do
190+
let ballE = ball rs
191+
leftE = leftPaddle rs
192+
rightE = rightPaddle rs
154193
mBallT <- lookup @_ @Transform2D ballE
155194
mBall <- lookup @_ @Ball ballE
156195
mLeftT <- lookup @_ @Transform2D leftE
157196
mRightT <- lookup @_ @Transform2D rightE
158197

159198
case (mBallT, mBall, mLeftT, mRightT) of
160-
(Just ballT, Just ball, Just leftT, Just rightT) -> do
199+
(Just ballT, Just ball', Just leftT, Just rightT) -> do
161200
-- Get current velocity from Ball component
162-
let velX = ballVelX ball
163-
velY = ballVelY ball
201+
let velX = ballVelX ball'
202+
velY = ballVelY ball'
164203

165204
let V2 bx by = transformTranslation ballT
166205
V2 _ ly = transformTranslation leftT
@@ -210,24 +249,26 @@ updateBall dt ballE leftE rightE = do
210249
then (Nothing, rightPaddleX - paddleW / 2 - ballR, clampedBy, -(abs velX))
211250
else
212251
if newBx + ballR < 0
213-
then do
214-
(Just (rightE, "Right"), centerX, centerY, ballInitSpeedX)
252+
then (Just (rightE, False), centerX, centerY, ballInitSpeedX)
215253
else
216254
if newBx - ballR > fromIntegral windowW
217-
then (Just (leftE, "Left"), centerX, centerY, -ballInitSpeedX)
255+
then (Just (leftE, True), centerX, centerY, -ballInitSpeedX)
218256
else (Nothing, newBx, clampedBy, velX)
219257

220258
-- Scoring
221259
case res of
222-
Just (e, s) -> do
260+
Just (e, isLeft) -> do
223261
mPaddle <- lookup @_ @Paddle e
224262
let !score = case mPaddle of
225263
Just p -> paddleScore p + 1
226264
Nothing -> 1
227265
insert e . bundle $ Paddle score
228-
liftIO $ do
229-
putStrLn $ s ++ " scores! Score: " ++ show score
230-
hFlush stdout
266+
-- Update the appropriate score label
267+
let labelE = if isLeft then leftScoreLabel rs else rightScoreLabel rs
268+
mLabel <- lookup @_ @Label labelE
269+
case mLabel of
270+
Just lbl -> insert labelE . bundle $ lbl {labelText = show score}
271+
Nothing -> return ()
231272
Nothing -> return ()
232273

233274
-- Update ball transform and velocity

0 commit comments

Comments
 (0)