summaryrefslogtreecommitdiff
path: root/Djup/src
diff options
context:
space:
mode:
authorJoel Stålnacke <joel@saker.fi>2026-03-19 22:30:56 +0200
committerJoel Stålnacke <joel@saker.fi>2026-03-19 22:30:56 +0200
commit745406dc65aecc438a53f96badc387a32b7a338f (patch)
treecc597855dac943efe627fce160782585e27feadf /Djup/src
parent3b60cd682120947119f442bb71ab2a5e98decccc (diff)
Add Mibo project
The Djup project is DesktopGL project
Diffstat (limited to 'Djup/src')
-rw-r--r--Djup/src/Content/Content.mgcb14
-rw-r--r--Djup/src/Djup.fsproj32
-rw-r--r--Djup/src/Icon.bmpbin0 -> 262282 bytes
-rw-r--r--Djup/src/Icon.icobin0 -> 147541 bytes
-rw-r--r--Djup/src/Program.fs153
-rw-r--r--Djup/src/app.manifest29
-rw-r--r--Djup/src/packages.lock.json72
7 files changed, 300 insertions, 0 deletions
diff --git a/Djup/src/Content/Content.mgcb b/Djup/src/Content/Content.mgcb
new file mode 100644
index 0000000..8b0866b
--- /dev/null
+++ b/Djup/src/Content/Content.mgcb
@@ -0,0 +1,14 @@
+
+#----------------------------- Global Properties ----------------------------#
+
+/outputDir:bin/$(Platform)
+/intermediateDir:obj/$(Platform)
+/platform:DesktopGL
+/config:
+/profile:Reach
+/compress:False
+
+#-------------------------------- References --------------------------------#
+
+
+#---------------------------------- Content ---------------------------------#
diff --git a/Djup/src/Djup.fsproj b/Djup/src/Djup.fsproj
new file mode 100644
index 0000000..dad45e9
--- /dev/null
+++ b/Djup/src/Djup.fsproj
@@ -0,0 +1,32 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <OutputType>WinExe</OutputType>
+ <TargetFramework>net10.0</TargetFramework>
+ <RollForward>Major</RollForward>
+ <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
+ <PublishReadyToRun>false</PublishReadyToRun>
+ <TieredCompilation>false</TieredCompilation>
+ <ApplicationManifest>app.manifest</ApplicationManifest>
+ <ApplicationIcon>Icon.ico</ApplicationIcon>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <Compile Include="Program.fs" />
+ <EmbeddedResource Include="Icon.ico" />
+ <EmbeddedResource Include="Icon.bmp" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <PackageReference Include="Mibo" Version="1.*" />
+ <PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.*" />
+ <PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.*" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <MonoGameContentReference Include="Content/Content.mgcb" />
+ </ItemGroup>
+
+ <Import Project="../../Djup.Native/scripts/AddRuntimeTargetsToDepsJson.targets" />
+
+</Project>
diff --git a/Djup/src/Icon.bmp b/Djup/src/Icon.bmp
new file mode 100644
index 0000000..2b48165
--- /dev/null
+++ b/Djup/src/Icon.bmp
Binary files differ
diff --git a/Djup/src/Icon.ico b/Djup/src/Icon.ico
new file mode 100644
index 0000000..7d9dec1
--- /dev/null
+++ b/Djup/src/Icon.ico
Binary files differ
diff --git a/Djup/src/Program.fs b/Djup/src/Program.fs
new file mode 100644
index 0000000..2427252
--- /dev/null
+++ b/Djup/src/Program.fs
@@ -0,0 +1,153 @@
+module Djup.Program
+
+open System
+open Microsoft.Xna.Framework
+open Microsoft.Xna.Framework.Graphics
+open Microsoft.Xna.Framework.Input
+open Mibo.Elmish
+open Mibo.Elmish.Graphics2D
+open Mibo.Input
+
+// ─────────────────────────────────────────────────────────────
+// Input
+// ─────────────────────────────────────────────────────────────
+
+type GameAction =
+ | MoveLeft
+ | MoveRight
+ | MoveUp
+ | MoveDown
+
+let inputMap =
+ InputMap.empty
+ |> InputMap.key MoveLeft Keys.Left
+ |> InputMap.key MoveLeft Keys.A
+ |> InputMap.key MoveRight Keys.Right
+ |> InputMap.key MoveRight Keys.D
+ |> InputMap.key MoveUp Keys.Up
+ |> InputMap.key MoveUp Keys.W
+ |> InputMap.key MoveDown Keys.Down
+ |> InputMap.key MoveDown Keys.S
+
+// ─────────────────────────────────────────────────────────────
+// Model
+// ─────────────────────────────────────────────────────────────
+
+type Model = {
+ Position: Vector2
+ Velocity: Vector2
+ Input: ActionState<GameAction>
+}
+
+// ─────────────────────────────────────────────────────────────
+// Messages
+// ─────────────────────────────────────────────────────────────
+
+type Msg =
+ | Tick of GameTime
+ | InputChanged of ActionState<GameAction>
+
+// ─────────────────────────────────────────────────────────────
+// Init
+// ─────────────────────────────────────────────────────────────
+
+let init(ctx: GameContext) : struct (Model * Cmd<Msg>) =
+ let model = {
+ Position = Vector2(400.f, 300.f)
+ Velocity = Vector2(200.f, 150.f)
+ Input = ActionState.empty
+ }
+
+ model, Cmd.none
+
+// ─────────────────────────────────────────────────────────────
+// Update
+// ─────────────────────────────────────────────────────────────
+
+let update (msg: Msg) (model: Model) : struct (Model * Cmd<Msg>) =
+ match msg with
+ | InputChanged input -> { model with Input = input }, Cmd.none
+
+ | Tick gt ->
+ let dt = float32 gt.ElapsedGameTime.TotalSeconds
+
+ // Manual movement
+ let speed = 200.f
+ let mutable manualVelocity = Vector2.Zero
+
+ if model.Input.Held.Contains MoveLeft then
+ manualVelocity.X <- manualVelocity.X - speed
+
+ if model.Input.Held.Contains MoveRight then
+ manualVelocity.X <- manualVelocity.X + speed
+
+ if model.Input.Held.Contains MoveUp then
+ manualVelocity.Y <- manualVelocity.Y - speed
+
+ if model.Input.Held.Contains MoveDown then
+ manualVelocity.Y <- manualVelocity.Y + speed
+
+ // Bouncing logic
+ let mutable velocity = model.Velocity
+
+ let mutable position =
+ model.Position + (velocity * dt) + (manualVelocity * dt)
+
+ if position.X < 0.f || position.X > 800.f - 32.f then
+ velocity.X <- -velocity.X
+
+ if position.Y < 0.f || position.Y > 600.f - 32.f then
+ velocity.Y <- -velocity.Y
+
+ {
+ model with
+ Position = position
+ Velocity = velocity
+ },
+ Cmd.none
+
+// ─────────────────────────────────────────────────────────────
+// View
+// ─────────────────────────────────────────────────────────────
+
+let view (ctx: GameContext) (model: Model) (buffer: RenderBuffer<RenderCmd2D>) =
+ // Draw player (using a 1x1 pixel texture if no asset loaded, or load one)
+ let pixel =
+ Assets.getOrCreate
+ "pixel"
+ (fun gd ->
+ let t = new Texture2D(gd, 1, 1)
+ t.SetData([| Color.White |])
+ t)
+ ctx
+
+ Draw2D.sprite
+ pixel
+ (Rectangle(int model.Position.X, int model.Position.Y, 32, 32))
+ |> Draw2D.withColor Color.Red
+ |> Draw2D.submit buffer
+
+// ─────────────────────────────────────────────────────────────
+// Program
+// ─────────────────────────────────────────────────────────────
+
+[<EntryPoint>]
+let main _ =
+ let program =
+ Program.mkProgram init update
+ |> Program.withAssets
+ |> Program.withRenderer(fun g -> Batch2DRenderer.create g view)
+ |> Program.withInput
+ |> Program.withSubscription(fun ctx _ ->
+ InputMapper.subscribeStatic inputMap InputChanged ctx)
+ |> Program.withTick Tick
+ |> Program.withConfig(fun (game, graphics) ->
+ game.Content.RootDirectory <- "Content"
+ game.Window.Title <- "Mibo 2D Game"
+ game.IsMouseVisible <- true
+ graphics.PreferredBackBufferWidth <- 800
+ graphics.PreferredBackBufferHeight <- 600)
+
+ use game = new ElmishGame<Model, Msg>(program)
+ game.Run()
+ 0
diff --git a/Djup/src/app.manifest b/Djup/src/app.manifest
new file mode 100644
index 0000000..b27ce83
--- /dev/null
+++ b/Djup/src/app.manifest
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
+ <assemblyIdentity version="1.0.0.0" name="Djup"/>
+ <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
+ <security>
+ <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
+ <requestedExecutionLevel level="asInvoker" uiAccess="false" />
+ </requestedPrivileges>
+ </security>
+ </trustInfo>
+
+ <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+ <application>
+ <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
+ <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
+ <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
+ <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
+ <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
+ </application>
+ </compatibility>
+
+ <application xmlns="urn:schemas-microsoft-com:asm.v3">
+ <windowsSettings>
+ <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
+ <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">permonitorv2,permonitor</dpiAwareness>
+ </windowsSettings>
+ </application>
+
+</assembly>
diff --git a/Djup/src/packages.lock.json b/Djup/src/packages.lock.json
new file mode 100644
index 0000000..64ca908
--- /dev/null
+++ b/Djup/src/packages.lock.json
@@ -0,0 +1,72 @@
+{
+ "version": 1,
+ "dependencies": {
+ "net10.0": {
+ "FSharp.Core": {
+ "type": "Direct",
+ "requested": "[10.1.201, )",
+ "resolved": "10.1.201",
+ "contentHash": "s5w9LWYurZ9yZdIppoIaYLkRadyT5s3u0wbQCb0J4bQd3ubIlIWQ3Nd5+ll1y3pv5OnTS373dP8T1S/BP46QXg=="
+ },
+ "Mibo": {
+ "type": "Direct",
+ "requested": "[1.*, )",
+ "resolved": "1.6.0",
+ "contentHash": "HcElja4XxQ8E1vJc93+78Sb/lQB6jTy0VyOuMQRqwQfHeo4tQMx+6JkLj2OJVaeWE4BhC/P+C5tcONLnW3RGfg==",
+ "dependencies": {
+ "FSharp.Core": "10.0.102",
+ "FSharp.UMX": "1.1.0",
+ "JDeck": "1.0.0"
+ }
+ },
+ "MonoGame.Content.Builder.Task": {
+ "type": "Direct",
+ "requested": "[3.8.*, )",
+ "resolved": "3.8.4.1",
+ "contentHash": "jf6IZXMiOhuybRaWQt//u+804yzMRGk3ZRvlBJG/0iusRwTunJsQvA6tMMJJc7gjUrY6rUkzRqwinKWXugyHfA=="
+ },
+ "MonoGame.Framework.DesktopGL": {
+ "type": "Direct",
+ "requested": "[3.8.*, )",
+ "resolved": "3.8.4.1",
+ "contentHash": "YybxIIT5+Ky78E/XdkS0glyluMr2EeDZwx2LqXULAOCqiKt1+aDrjPZaqLL5qpNgBcMEHUeZJ4YjWe4TAZlWLw==",
+ "dependencies": {
+ "MonoGame.Library.OpenAL": "1.24.3.2",
+ "MonoGame.Library.SDL": "2.32.2.1",
+ "NVorbis": "0.10.4"
+ }
+ },
+ "FSharp.UMX": {
+ "type": "Transitive",
+ "resolved": "1.1.0",
+ "contentHash": "0+4w4/yBL5z7w1/k198ooPbfMqkzMSXPRVZEVingnwAdjM//QIFG25eJbB3RtoSQAusBwV5B3VcSudxJejd5Bg==",
+ "dependencies": {
+ "FSharp.Core": "4.3.4"
+ }
+ },
+ "JDeck": {
+ "type": "Transitive",
+ "resolved": "1.0.0",
+ "contentHash": "a4d+USHnlc3+zPZb7MOKXD58BbVMaO1sajROxPQH5m+g08QtqVcr4PlNs6cT5QuP13lKpHlw9X+9UlAcXmguYA==",
+ "dependencies": {
+ "FSharp.Core": "9.0.100"
+ }
+ },
+ "MonoGame.Library.OpenAL": {
+ "type": "Transitive",
+ "resolved": "1.24.3.2",
+ "contentHash": "nGRsXQXs+NSUC3C5w90hFQfyKdZPpBnHnyg2w+Dw/2pUH7s+CoRWTJNYbzzdJf3+aeUvfvG4rTbFvMKDDj5olA=="
+ },
+ "MonoGame.Library.SDL": {
+ "type": "Transitive",
+ "resolved": "2.32.2.1",
+ "contentHash": "T4E2ppGlSTC2L9US1rxtdg3qTbarRzNId31xZoumUW9cf9Nq8nRQPMu9GzvZGrhfSySf0+UWPEj1rlicps+P/w=="
+ },
+ "NVorbis": {
+ "type": "Transitive",
+ "resolved": "0.10.4",
+ "contentHash": "WYnil3DhQHzjCY0dM9I2B3r1vWip90AOuQd25KE4NrjPQBg0tBJFluRLm5YPnO5ZLDmwrfosY8jCQGQRmWI/Pg=="
+ }
+ }
+ }
+} \ No newline at end of file