Skip to content

Commit f398a56

Browse files
Examples updated
1 parent f7b0b56 commit f398a56

File tree

135 files changed

+5600
-3
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

135 files changed

+5600
-3
lines changed

.github/workflows/ci.yml

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
name: CI
2+
on: [workflow_dispatch, push, pull_request]
3+
jobs:
4+
build:
5+
runs-on: ubuntu-latest
6+
steps:
7+
- uses: actions/checkout@v1
8+
- uses: coursier/cache-action@v6
9+
- uses: olafurpg/setup-scala@v11
10+
with:
11+
java-version: [email protected]
12+
- name: Indigo Examples Compile & Test
13+
run: bash build.sh

.gitignore

+30-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
1+
12
*.class
23
*.log
34
.DS_Store
5+
6+
# Windows specific
7+
null/
8+
9+
# Scala-cli specific
10+
.scala-build
11+
12+
# mill specific
413
out
514
publish.sh
15+
credentials.sh
16+
17+
# sbt specific
618
sbt
719
.sbt-local
820
.cache
@@ -12,12 +24,27 @@ dist
1224
target
1325
lib_managed
1426
src_managed
27+
credentials.sbt
28+
29+
# IDE specific
1530
.idea
1631
*.iml
17-
.vscode
32+
.vscode/
33+
.vim
34+
.dotty-ide-disabled
35+
*.swp
36+
1837
node_modules
1938
.metals/
2039
.bloop
2140
metals.sbt
22-
.dotty-ide-disabled
23-
.bsp
41+
.bsp/
42+
.ammonite
43+
.coursier
44+
45+
indigo/site/public/
46+
website/build/
47+
48+
# Direnv
49+
.direnv
50+
.envrc

.scalafix.conf

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
rules = [
2+
DisableSyntax,
3+
OrganizeImports
4+
]
5+
6+
OrganizeImports {
7+
removeUnused = false
8+
}
9+
10+
DisableSyntax {
11+
noVars = true
12+
noThrows = true
13+
noNulls = true
14+
noReturns = true
15+
noWhileLoops = true
16+
noAsInstanceOf = false # Doesn't seem to work correctly
17+
noIsInstanceOf = false # Doesn't seem to work correctly
18+
noXml = true
19+
noDefaultArgs = true
20+
noFinalVal = true
21+
noFinalize = true
22+
noValPatterns = true
23+
# noUniversalEquality = false # handled by scala 3
24+
# noUniversalEqualityMessage = "== and != are unsafe since they allow comparing two unrelated types"
25+
# regex = []
26+
}

.scalafmt.conf

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
version = 3.7.2
2+
runner.dialect = scala3
3+
style = defaultWithAlign
4+
maxColumn = 120
5+
rewrite.rules = [RedundantBraces,RedundantParens,PreferCurlyFors]
6+
danglingParentheses.preset = true

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
# Indigo Examples
22

33
Examples of how to build things in Indigo using the latest public release.
4+
5+
Enter the sbt console (`sbt` in your terminal in the project root) to see a list of runnable demos.

assetLoading/assets/RetroGameJump.mp3

11.4 KB
Binary file not shown.

assetLoading/assets/graphics.png

3.13 KB
Loading
523 Bytes
Loading
274 Bytes
Loading
752 Bytes
Loading
315 Bytes
Loading

assetLoading/assets/test.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Billy,Bobby,Fred
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
package com.example.assetloading
2+
3+
import indigo._
4+
import indigoextras.subsystems._
5+
import indigoextras.ui._
6+
7+
import scala.scalajs.js.annotation._
8+
9+
@JSExportTopLevel("IndigoGame")
10+
object AssetLoadingExample extends IndigoDemo[Unit, Unit, MyGameModel, MyViewModel] {
11+
12+
val eventFilters: EventFilters = EventFilters.Permissive
13+
14+
def boot(flags: Map[String, String]): Outcome[BootResult[Unit]] =
15+
Outcome {
16+
BootResult
17+
.noData(
18+
defaultGameConfig.withMagnification(2)
19+
)
20+
.withAssets(Assets.assets)
21+
.withSubSystems(AssetBundleLoader)
22+
}
23+
24+
given CanEqual[Option[String], Option[String]] = CanEqual.derived
25+
26+
def setup(bootData: Unit, assetCollection: AssetCollection, dice: Dice): Outcome[Startup[Unit]] =
27+
Outcome {
28+
assetCollection.findTextDataByName(AssetName("text")) match {
29+
case Some(value) =>
30+
println("Loaded text! " + value)
31+
Startup.Success(()).addShaders(MyColoredEntity.shader)
32+
case None =>
33+
Startup.Success(())
34+
}
35+
}
36+
37+
def initialModel(startupData: Unit): Outcome[MyGameModel] =
38+
Outcome(MyGameModel(loaded = false))
39+
40+
def initialViewModel(startupData: Unit, model: MyGameModel): Outcome[MyViewModel] =
41+
Outcome {
42+
MyViewModel(
43+
button = Button(
44+
buttonAssets = Assets.buttonAssets,
45+
bounds = Rectangle(10, 10, 16, 16),
46+
depth = Depth(2)
47+
).withUpActions {
48+
println("Start loading assets...")
49+
Batch(AssetBundleLoaderEvent.Load(BindingKey("Junction box assets"), Assets.junctionboxImageAssets ++ Assets.otherAssetsToLoad))
50+
}
51+
)
52+
}
53+
54+
@SuppressWarnings(Array("org.wartremover.warts.ToString"))
55+
def updateModel(context: FrameContext[Unit], model: MyGameModel): GlobalEvent => Outcome[MyGameModel] = {
56+
case AssetBundleLoaderEvent.Started(key) =>
57+
println("Load started! " + key.toString())
58+
Outcome(model)
59+
60+
case AssetBundleLoaderEvent.LoadProgress(key, percent, completed, total) =>
61+
println(s"In progress...: ${key.toString()} - ${percent.toString()}%, ${completed.toString()} of ${total.toString()}")
62+
Outcome(model)
63+
64+
case AssetBundleLoaderEvent.Success(key) =>
65+
println("Got it! " + key.toString())
66+
Outcome(model.copy(loaded = true)).addGlobalEvents(PlaySound(AssetName("sfx"), Volume.Max))
67+
68+
case AssetBundleLoaderEvent.Failure(key, message) =>
69+
println(s"Lost it... '$message' " + key.toString())
70+
Outcome(model)
71+
72+
case _ =>
73+
Outcome(model)
74+
}
75+
76+
def updateViewModel(context: FrameContext[Unit], model: MyGameModel, viewModel: MyViewModel): GlobalEvent => Outcome[MyViewModel] = {
77+
case FrameTick =>
78+
viewModel.button.update(context.inputState.mouse).map { btn =>
79+
viewModel.copy(button = btn)
80+
}
81+
82+
case _ =>
83+
Outcome(viewModel)
84+
}
85+
86+
def present(context: FrameContext[Unit], model: MyGameModel, viewModel: MyViewModel): Outcome[SceneUpdateFragment] = {
87+
val stuff =
88+
if model.loaded then
89+
Batch(
90+
Graphic(Rectangle(0, 0, 64, 64), 1, Assets.junctionBoxMaterial)
91+
.moveTo(30, 30),
92+
MyColoredEntity(Point(0, 50))
93+
)
94+
else Batch.empty
95+
96+
Outcome(
97+
SceneUpdateFragment(viewModel.button.draw :: stuff)
98+
.addLights(DirectionLight.default)
99+
)
100+
}
101+
}
102+
103+
final case class MyGameModel(loaded: Boolean)
104+
final case class MyViewModel(button: Button)
105+
106+
object Assets {
107+
108+
val junctionBoxAlbedo: AssetName = AssetName("junctionbox_albedo")
109+
val junctionBoxEmission: AssetName = AssetName("junctionbox_emission")
110+
val junctionBoxNormal: AssetName = AssetName("junctionbox_normal")
111+
val junctionBoxSpecular: AssetName = AssetName("junctionbox_specular")
112+
113+
def junctionboxImageAssets: Set[AssetType] =
114+
Set(
115+
AssetType.Image(junctionBoxAlbedo, AssetPath("assets/" + junctionBoxAlbedo + ".png")),
116+
AssetType.Image(junctionBoxEmission, AssetPath("assets/" + junctionBoxEmission + ".png")),
117+
AssetType.Image(junctionBoxNormal, AssetPath("assets/" + junctionBoxNormal + ".png")),
118+
AssetType.Image(junctionBoxSpecular, AssetPath("assets/" + junctionBoxSpecular + ".png"))
119+
)
120+
121+
def otherAssetsToLoad: Set[AssetType] =
122+
Set(
123+
AssetType.Text(AssetName("text"), AssetPath("assets/test.txt")),
124+
AssetType.Audio(AssetName("sfx"), AssetPath("assets/RetroGameJump.mp3"))
125+
)
126+
127+
val junctionBoxMaterial: Material.Bitmap =
128+
Material.Bitmap(
129+
junctionBoxAlbedo,
130+
LightingModel.Lit(
131+
junctionBoxEmission,
132+
junctionBoxNormal,
133+
junctionBoxSpecular
134+
)
135+
)
136+
137+
def assets: Set[AssetType] =
138+
Set(
139+
AssetType.Image(AssetName("graphics"), AssetPath("assets/graphics.png"))
140+
)
141+
142+
val buttonAssets: ButtonAssets =
143+
ButtonAssets(
144+
up = Graphic(0, 0, 16, 16, 2, Material.Bitmap(AssetName("graphics"))).withCrop(32, 0, 16, 16),
145+
over = Graphic(0, 0, 16, 16, 2, Material.Bitmap(AssetName("graphics"))).withCrop(32, 16, 16, 16),
146+
down = Graphic(0, 0, 16, 16, 2, Material.Bitmap(AssetName("graphics"))).withCrop(32, 32, 16, 16)
147+
)
148+
149+
}
150+
151+
final case class MyColoredEntity(position: Point) extends EntityNode[MyColoredEntity]:
152+
def size: Size = Size(32, 32)
153+
def flip: Flip = Flip.default
154+
def ref: Point = Point.zero
155+
def rotation: Radians = Radians.zero
156+
def scale: Vector2 = Vector2.one
157+
def depth: Depth = Depth(1)
158+
159+
def withDepth(newDepth: Depth): MyColoredEntity =
160+
this
161+
162+
def toShaderData: ShaderData =
163+
ShaderData(MyColoredEntity.shader.id)
164+
165+
val eventHandler: ((MyColoredEntity, GlobalEvent)) => Option[indigo.shared.events.GlobalEvent] =
166+
Function.const(None)
167+
val eventHandlerEnabled: Boolean = false
168+
169+
object MyColoredEntity:
170+
val shader: EntityShader =
171+
EntityShader
172+
.Source(ShaderId("my-colored-shader"))
173+
.withFragmentProgram(
174+
"""
175+
|void fragment() {
176+
| COLOR = vec4(0.0, 1.0, 0.0, 1.0);
177+
|}
178+
|""".stripMargin
179+
)

audio/assets/RetroGameJump.mp3

11.4 KB
Binary file not shown.

audio/assets/graphics.png

3.13 KB
Loading

audio/assets/march_of_steampunk.mp3

1.44 MB
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package indigoexamples
2+
3+
import indigo._
4+
import indigoextras.ui._
5+
6+
import scala.scalajs.js.annotation._
7+
8+
@JSExportTopLevel("IndigoGame")
9+
object AudioExample extends IndigoDemo[Unit, Unit, Unit, Button] {
10+
11+
val eventFilters: EventFilters = EventFilters.Permissive
12+
13+
def boot(flags: Map[String, String]): Outcome[BootResult[Unit]] =
14+
Outcome {
15+
BootResult
16+
.noData(defaultGameConfig)
17+
.withAssets(
18+
AssetType.Image(AssetName("graphics"), AssetPath("assets/graphics.png")),
19+
AssetType.Audio(AssetName("bounce"), AssetPath("assets/RetroGameJump.mp3")),
20+
AssetType.Audio(AssetName("music"), AssetPath("assets/march_of_steampunk.mp3"))
21+
)
22+
}
23+
24+
def setup(bootData: Unit, assetCollection: AssetCollection, dice: Dice): Outcome[Startup[Unit]] =
25+
Outcome(Startup.Success(()))
26+
27+
def initialModel(startupData: Unit): Outcome[Unit] =
28+
Outcome(())
29+
30+
def initialViewModel(startupData: Unit, model: Unit): Outcome[Button] =
31+
Outcome(
32+
Button(
33+
buttonAssets = ButtonAssets(
34+
up = Graphic(0, 0, 16, 16, 2, Material.Bitmap(AssetName("graphics"))).withCrop(32, 0, 16, 16),
35+
over = Graphic(0, 0, 16, 16, 2, Material.Bitmap(AssetName("graphics"))).withCrop(32, 16, 16, 16),
36+
down = Graphic(0, 0, 16, 16, 2, Material.Bitmap(AssetName("graphics"))).withCrop(32, 32, 16, 16)
37+
),
38+
bounds = Rectangle(10, 10, 16, 16),
39+
depth = Depth(2)
40+
).withUpActions(PlaySound(AssetName("bounce"), Volume.Max))
41+
)
42+
43+
def updateModel(context: FrameContext[Unit], model: Unit): GlobalEvent => Outcome[Unit] = {
44+
case _ =>
45+
Outcome(model)
46+
}
47+
48+
def updateViewModel(context: FrameContext[Unit], model: Unit, viewModel: Button): GlobalEvent => Outcome[Button] = {
49+
case FrameTick =>
50+
viewModel.update(context.inputState.mouse)
51+
52+
case _ =>
53+
Outcome(viewModel)
54+
}
55+
56+
def present(context: FrameContext[Unit], model: Unit, viewModel: Button): Outcome[SceneUpdateFragment] =
57+
Outcome(
58+
SceneUpdateFragment(viewModel.draw)
59+
.withAudio(
60+
SceneAudio(
61+
SceneAudioSource(BindingKey("My bg music"), PlaybackPattern.SingleTrackLoop(Track(AssetName("music"))))
62+
)
63+
)
64+
)
65+
}
66+
67+
final case class MyGameModel(button: Button, count: Int)

automata/assets/boxy_font.png

4.31 KB
Loading

automata/assets/graphics.png

3.13 KB
Loading

0 commit comments

Comments
 (0)