diff --git a/Celeste64.csproj b/Celeste64.csproj
index fd14a13..a15310f 100644
--- a/Celeste64.csproj
+++ b/Celeste64.csproj
@@ -10,6 +10,7 @@
true
false
x64
+ true
diff --git a/Content/Maps/1.map b/Content/Maps/1.map
index 2bcf466..2f44a14 100644
--- a/Content/Maps/1.map
+++ b/Content/Maps/1.map
@@ -3917,7 +3917,7 @@
}
// brush 422
{
-( 3456 3104 576 ) ( 3456 3105 576 ) ( 3456 3104 577 ) rock_1 0 0 0 1 1
+( 3456 3104 576 ) ( 3456 3105 576 ) ( 3456 3104 577 ) wood_3 0 0 0 1 1
( 3456 3104 576 ) ( 3456 3104 577 ) ( 3457 3104 576 ) rock_1 0 0 0 1 1
( 3584 3104 544 ) ( 3712 3616 288 ) ( 3584 3616 288 ) wall_ruined_2 0 0 0 1 1
( 3456 3104 288 ) ( 3457 3104 288 ) ( 3456 3105 288 ) rock_1 0 0 0 1 1
@@ -14991,12 +14991,12 @@
"_tb_layer" "3"
// brush 0
{
-( 3136 3168 480 ) ( 3136 3169 480 ) ( 3136 3168 481 ) rock_1 0 0 0 1 1
-( 3040 3360 480 ) ( 3040 3360 481 ) ( 3041 3360 480 ) rock_1 0 0 0 1 1
-( 3040 3168 288 ) ( 3041 3168 288 ) ( 3040 3169 288 ) rock_1 0 0 0 1 1
-( 3136 3296 480 ) ( 3136 3297 480 ) ( 3137 3296 480 ) wall_ruined_6 -64 0 0 1 1
-( 3136 3518 512 ) ( 3137 3518 512 ) ( 3136 3518 513 ) wood_4 0 0 0 1 1
-( 3264 3296 512 ) ( 3264 3296 513 ) ( 3264 3297 512 ) rock_1 0 0 0 1 1
+( 3136 3360 480 ) ( 3136 3424 288 ) ( 3136 3518 288 ) rock_1 0 0 0 1 1
+( 3264 3360 480 ) ( 3264 3424 288 ) ( 3136 3424 288 ) rock_1 0 0 0 1 1
+( 3264 3424 288 ) ( 3264 3518 288 ) ( 3136 3518 288 ) rock_1 0 0 0 1 1
+( 3136 3518 480 ) ( 3264 3518 480 ) ( 3264 3360 480 ) wall_ruined_6 -64 0 0 1 1
+( 3264 3518 288 ) ( 3264 3518 480 ) ( 3136 3518 480 ) wood_4 0 0 0 1 1
+( 3264 3360 480 ) ( 3264 3518 480 ) ( 3264 3518 288 ) rock_1 0 0 0 1 1
}
}
// entity 657
diff --git a/Content/Sprites/Controls/PC/cancel.png b/Content/Sprites/Controls/PC/cancel.png
new file mode 100644
index 0000000..170b55c
Binary files /dev/null and b/Content/Sprites/Controls/PC/cancel.png differ
diff --git a/Content/Sprites/Controls/PC/confirm.png b/Content/Sprites/Controls/PC/confirm.png
new file mode 100644
index 0000000..d87b2d9
Binary files /dev/null and b/Content/Sprites/Controls/PC/confirm.png differ
diff --git a/ReadMe.md b/ReadMe.md
index db242c5..a281ccd 100644
--- a/ReadMe.md
+++ b/ReadMe.md
@@ -16,14 +16,14 @@ You can find prebuilt version of the game on [itch.io](https://maddymakesgamesin
### Tools Used
- [TrenchBroom](https://trenchbroom.github.io/): For Level Editing
- - [Blender](https://www.blender.org/): For creating 3D Model
+ - [Blender](https://www.blender.org/): For creating 3D Models
- [Aseprite](https://www.aseprite.org/): For drawing Textures
### Resources Used
- [khronos glTF Tutorials](https://github.khronos.org/glTF-Tutorials/gltfTutorial/gltfTutorial_020_Skins.html#the-joint-matrices): To figure out how Mesh Skins/Bones work
- [LearnOpenGL](https://learnopengl.com/Advanced-OpenGL/Depth-testing): For general rendering concepts / normalizing Depth
- [Kenny's Input Prompts](https://kenney.nl/assets/input-prompts): For UI Button Prompts
- - [Renogare](https://www.dafont.com/renogare.font): Font for Text
+ - [Renogare](https://www.dafont.com/renogare.font): Main font
### Created By ...
- [Maddy Thorson](http://maddymakesgames.com/)
diff --git a/Source/Actors/Badeline.cs b/Source/Actors/Badeline.cs
index b9cf559..05397ca 100644
--- a/Source/Actors/Badeline.cs
+++ b/Source/Actors/Badeline.cs
@@ -19,7 +19,7 @@ public Badeline() : base(Assets.Models["badeline"])
mat.Color = hairColor;
mat.Effects = 0;
}
- mat.Set("u_silhouette_color", hairColor);
+ mat.SilhouetteColor = hairColor;
}
hair = new()
diff --git a/Source/Actors/Player.cs b/Source/Actors/Player.cs
index 2d8864d..cab2b9a 100644
--- a/Source/Actors/Player.cs
+++ b/Source/Actors/Player.cs
@@ -629,7 +629,7 @@ public void SetHairColor(Color color)
mat.Color = color;
mat.Effects = 0;
}
- mat.Set("u_silhouette_color", color);
+ mat.SilhouetteColor = color;
}
Hair.Color = color;
@@ -1489,7 +1489,7 @@ private void StClimbingUpdate()
// don't climb over ledges into spikes
// (you can still climb up into spikes if they're on the same wall as you)
- if (move.Z > 0 && World.Overlaps(Position + Vec3.UnitZ * 6 + forward * (ClimbCheckDist + 1)))
+ if (move.Z > 0 && World.Overlaps(Position + Vec3.UnitZ * ClimbCheckDist + forward * (ClimbCheckDist + 1)))
move.Z = 0;
// don't move left/right around into a spikes
@@ -2067,16 +2067,30 @@ private CoEnumerator StCassetteRoutine()
if (cassette != null)
{
- if (World.Entry.Submap || !Assets.Maps.ContainsKey(cassette.Map))
+ if (World.Entry.Submap)
{
- Game.Instance.Goto(new Transition()
+ Game.Instance.Goto(new Transition()
{
Mode = Transition.Modes.Pop,
ToPause = true,
ToBlack = new SpotlightWipe(),
StopMusic = true
});
- }
+ }
+ //Saves and quits game if you collect a cassette with an empty map property when you're not in a submap
+ else if (!Assets.Maps.ContainsKey(cassette.Map))
+ {
+ Game.Instance.Goto(new Transition()
+ {
+ Mode = Transition.Modes.Replace,
+ Scene = () => new Overworld(true),
+ ToPause = true,
+ ToBlack = new SpotlightWipe(),
+ FromBlack = new SlideWipe(),
+ StopMusic = true,
+ Saving = true
+ });
+ }
else
{
Game.Instance.Goto(new Transition()
@@ -2282,4 +2296,4 @@ public bool CeilingCheck(out Vec3 pushout)
public void Stop() => velocity = Vec3.Zero;
#endregion
-}
\ No newline at end of file
+}
diff --git a/Source/Controls.cs b/Source/Controls.cs
index bfbc722..5781f04 100644
--- a/Source/Controls.cs
+++ b/Source/Controls.cs
@@ -88,13 +88,16 @@ public static void Consume()
private static string GetPromptLocation(string name)
{
- var gamepad = Input.Controllers[0].Gamepad;
+ var gamepadPure = Input.Controllers[0];
+ var gamepad = gamepadPure.Gamepad;
if (!prompts.TryGetValue(gamepad, out var list))
prompts[gamepad] = list = new();
if (!list.TryGetValue(name, out var lookup))
- list[name] = lookup = $"Controls/{GetControllerName(gamepad)}/{name}";
+ list[name] = lookup = !gamepadPure.Connected
+ ? $"Controls/PC/{name}"
+ : $"Controls/{GetControllerName(gamepad)}/{name}";
return lookup;
}
@@ -113,4 +116,4 @@ public static Subtexture GetPrompt(VirtualButton button)
{
return Assets.Subtextures.GetValueOrDefault(GetPromptLocation(button));
}
-}
\ No newline at end of file
+}
diff --git a/Source/Game.cs b/Source/Game.cs
index cf460c3..8b069d8 100644
--- a/Source/Game.cs
+++ b/Source/Game.cs
@@ -1,4 +1,4 @@
-using System.Diagnostics;
+using System.Diagnostics;
using System.Text.Json;
using Celeste64.SpeedrunUtils;
@@ -177,10 +177,7 @@ public override void Update()
// perform game save between transitions
if (transition.Saving)
- {
- using var stream = File.Create(Path.Join(App.UserPath, Save.FileName));
- Save.Serialize(stream, Save.Instance);
- }
+ Save.Instance.SaveToFile();
// perform transition
switch (transition.Mode)
@@ -337,7 +334,7 @@ public override void Render()
private FMOD.RESULT MusicTimelineCallback(FMOD.Studio.EVENT_CALLBACK_TYPE type, IntPtr _event, IntPtr parameters)
{
- // notify that an audio event happend (but handle it on the main thread)
+ // notify that an audio event happened (but handle it on the main thread)
if (transitionStep == TransitionStep.None)
audioBeatCounterEvent = true;
return FMOD.RESULT.OK;
diff --git a/Source/Graphics/Hair.cs b/Source/Graphics/Hair.cs
index 8bf1861..323be6d 100644
--- a/Source/Graphics/Hair.cs
+++ b/Source/Graphics/Hair.cs
@@ -154,7 +154,7 @@ public override void Render(ref RenderState state)
state.ModelMatrix = was;
Materials[0].Color = Color;
- Materials[0].Set("u_silhouette_color", Color);
+ Materials[0].SilhouetteColor = Color;
// draw hair
var call = new DrawCommand(state.Camera.Target, mesh, Materials[0])
diff --git a/Source/Graphics/Materials.cs b/Source/Graphics/Materials.cs
index abe4b72..e7bb2b5 100644
--- a/Source/Graphics/Materials.cs
+++ b/Source/Graphics/Materials.cs
@@ -25,7 +25,11 @@ public class DefaultMaterial : Material
public DefaultMaterial(Texture? texture = null)
: base(Assets.Shaders["Default"])
{
- Debug.Assert(Shader != null && Shader.Has(MatrixUniformName), $"Shader '{Shader.Name}' is missing '{MatrixUniformName}' uniform");
+ if (!(Shader?.Has(MatrixUniformName) ?? false))
+ {
+ Log.Warning($"Shader '{Shader?.Name}' is missing '{MatrixUniformName}' uniform");
+ }
+
Texture = texture;
Color = Color.White;
Effects = 1.0f;
@@ -34,13 +38,23 @@ public DefaultMaterial(Texture? texture = null)
public Matrix MVP
{
get => matrix;
- set => Set(MatrixUniformName, matrix = value);
+ set
+ {
+ matrix = value;
+ if (Shader?.Has(MatrixUniformName) ?? false)
+ Set(MatrixUniformName, value);
+ }
}
public Matrix Model
{
get => model;
- set => Set("u_model", model = value);
+ set
+ {
+ model = value;
+ if (Shader?.Has("u_model") ?? false)
+ Set("u_model", value);
+ }
}
public Texture? Texture
diff --git a/Source/Graphics/Skybox.cs b/Source/Graphics/Skybox.cs
index 43296fc..6637848 100644
--- a/Source/Graphics/Skybox.cs
+++ b/Source/Graphics/Skybox.cs
@@ -60,10 +60,14 @@ private static void AddFace(List verts, List indices, in Vec3
public void Render(in Camera camera, in Matrix transform, float size)
{
var mat = Matrix.CreateScale(size) * transform * camera.ViewProjection;
- material.Set("u_matrix", mat);
- material.Set("u_near", camera.NearPlane);
- material.Set("u_far", camera.FarPlane);
- material.Set("u_texture", Texture);
+ if (material.Shader?.Has("u_matrix") ?? false)
+ material.Set("u_matrix", mat);
+ if (material.Shader?.Has("u_near") ?? false)
+ material.Set("u_near", camera.NearPlane);
+ if (material.Shader?.Has("u_far") ?? false)
+ material.Set("u_far", camera.FarPlane);
+ if (material.Shader?.Has("u_texture") ?? false)
+ material.Set("u_texture", Texture);
DrawCommand cmd = new(camera.Target, mesh, material)
{
diff --git a/Source/Graphics/SpriteRenderer.cs b/Source/Graphics/SpriteRenderer.cs
index a49d0d6..b626cf8 100644
--- a/Source/Graphics/SpriteRenderer.cs
+++ b/Source/Graphics/SpriteRenderer.cs
@@ -58,13 +58,17 @@ public void Render(ref RenderState state, List sprites, bool postEffects
spriteMesh.SetVertices(CollectionsMarshal.AsSpan(spriteVertices));
spriteMesh.SetIndices(CollectionsMarshal.AsSpan(spriteIndices));
- spriteMaterial.Set("u_matrix", state.Camera.ViewProjection);
- spriteMaterial.Set("u_far", state.Camera.FarPlane);
- spriteMaterial.Set("u_near", state.Camera.NearPlane);
+ if (spriteMaterial.Shader?.Has("u_matrix") ?? false)
+ spriteMaterial.Set("u_matrix", state.Camera.ViewProjection);
+ if (spriteMaterial.Shader?.Has("u_far") ?? false)
+ spriteMaterial.Set("u_far", state.Camera.FarPlane);
+ if (spriteMaterial.Shader?.Has("u_near") ?? false)
+ spriteMaterial.Set("u_near", state.Camera.NearPlane);
foreach (var batch in spriteBatches)
{
- spriteMaterial.Set("u_texture", batch.Texture);
+ if (spriteMaterial.Shader?.Has("u_texture") ?? false)
+ spriteMaterial.Set("u_texture", batch.Texture);
var call = new DrawCommand(state.Camera.Target, spriteMesh, spriteMaterial)
{
diff --git a/Source/Helpers/Menu.cs b/Source/Helpers/Menu.cs
index c9ca104..42c16f0 100644
--- a/Source/Helpers/Menu.cs
+++ b/Source/Helpers/Menu.cs
@@ -5,6 +5,7 @@ public class Menu
{
public const float Spacing = 4 * Game.RelativeScale;
public const float SpacerHeight = 12 * Game.RelativeScale;
+ public const float TitleScale = 0.75f;
public abstract class Item
{
@@ -14,7 +15,25 @@ public abstract class Item
public virtual void Slide(int dir) {}
}
- public class Spacer : Item
+ public class Submenu(string label, Menu? rootMenu, Menu? submenu = null) : Item
+ {
+ private readonly string label = label;
+ public override string Label => label;
+ public override bool Pressed()
+ {
+ if (submenu != null)
+ {
+ Audio.Play(Sfx.ui_select);
+ submenu.Index = 0;
+ rootMenu?.PushSubMenu(submenu);
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ public class Spacer : Item
{
public override bool Selectable => false;
}
@@ -75,26 +94,33 @@ public override bool Pressed()
}
}
- public int Index
- {
- get => index;
- set => index = value;
- }
+ public int Index;
+ public string Title = string.Empty;
public bool Focused = true;
private readonly SpriteFont font;
private readonly List- items = [];
- private int index = 0;
+ private readonly Stack