Added 15-puzzles to the project.

main
sixtenhugosson 2024-01-21 21:01:00 +01:00
parent 8b2d19f096
commit 72d27870f0
17 changed files with 541 additions and 271 deletions

View File

@ -1,4 +1,4 @@
char * AssetPathLUT[7] =
char * AssetPathLUT[8] =
{
"",
"backgrounds/unknown.png",
@ -7,9 +7,10 @@ char * AssetPathLUT[7] =
"characters/test_normal.png",
"characters/test_happy.png",
"characters/monika_leaning.png",
"puzzles/duck.png",
};
bool AssetIsPermanentLUT[7] =
bool AssetIsPermanentLUT[8] =
{
true,
true,
@ -18,9 +19,10 @@ false,
false,
false,
false,
false,
};
char * AssetNameLUT[7] =
char * AssetNameLUT[8] =
{
"None",
"Error",
@ -29,9 +31,10 @@ char * AssetNameLUT[7] =
"ArthurNormal",
"ArthurHappy",
"MonikaLeaning",
"Duck",
};
r32 AssetScaleLUT[7] =
r32 AssetScaleLUT[8] =
{
0,
0,
@ -40,5 +43,6 @@ r32 AssetScaleLUT[7] =
0.017,
0.017,
0.033,
1,
};

View File

@ -1,10 +1,10 @@
extern char * AssetPathLUT[7];
extern char * AssetPathLUT[8];
extern bool AssetIsPermanentLUT[7];
extern bool AssetIsPermanentLUT[8];
extern char * AssetNameLUT[7];
extern char * AssetNameLUT[8];
extern r32 AssetScaleLUT[7];
extern r32 AssetScaleLUT[8];
typedef s32 asset_id;
enum
@ -16,6 +16,7 @@ AssetID_DDLCBackground,
AssetID_ArthurNormal,
AssetID_ArthurHappy,
AssetID_MonikaLeaning,
AssetID_Duck,
AssetID_COUNT,
};

View File

@ -133,6 +133,8 @@ static S2_CALL_FUNCTION(S2_Call_CharacterSet); // sets the state of a charac
static S2_CALL_FUNCTION(S2_Call_CharacterRemove); // removes a character
static S2_CALL_FUNCTION(S2_Call_CharacterSetTalking); // makes a character talking
static S2_CALL_FUNCTION(S2_Call_CharacterUnsetAllTalking); // makes no characters talking
static S2_CALL_FUNCTION(S2_Call_NavLoad); // loads a nav scene
static S2_CALL_FUNCTION(S2_Call_Puzzle15); // plays the 15-puzzle
global read_only scene2_call_function *S2_CallBindingLookup[] =
{
@ -146,6 +148,8 @@ S2_Call_CharacterSet,
S2_Call_CharacterRemove,
S2_Call_CharacterSetTalking,
S2_Call_CharacterUnsetAllTalking,
S2_Call_NavLoad,
S2_Call_Puzzle15,
};
global read_only string S2_CallNameLookup[] =
@ -160,5 +164,7 @@ StrComp("ctr_set"),
StrComp("ctr_remove"),
StrComp("ctr_set_talking"),
StrComp("ctr_unset_all_talking"),
StrComp("nav_load"),
StrComp("puzzle_15"),
};

View File

@ -132,7 +132,7 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
//- sixten: load startup scene
temp Scratch = GetScratch();
compiled_scene2 Scene = S2_CompiledFromString(Scratch.Arena, Platform_ReadEntireFile(Scratch.Arena, StrLit("data/while_test.vns")));
compiled_scene2 Scene = S2_CompiledFromString(Scratch.Arena, Platform_ReadEntireFile(Scratch.Arena, StrLit("data/omori.vns")));
SV_SetCurrentSource(&Scene);
ReleaseScratch(Scratch);

View File

@ -18,6 +18,11 @@
//- sixten: monika
{ MonikaLeaning, "characters/monika_leaning.png", false, 0.033 }
////////////////////////////////
//~ sixten: puzzles
{ Duck, "puzzles/duck.png", false, 1 }
}

View File

@ -1021,5 +1021,9 @@ static scene2_run_result S2_Run(arena *Arena, scene2_runtime *Runtime, compiled_
}
Done:;
if(Runtime->InstructionPointer >= ProcInfo->InstructionEnd)
{
S2_SetCurrentProc(Runtime, S_EmptyProcInfo);
}
return(Result);
}

View File

@ -91,6 +91,8 @@ struct scene2_proc_info
u64 InstructionEnd;
};
global scene2_proc_info S_EmptyProcInfo = {StrComp(""), 0, 0};
struct scene2_proc_node
{
scene2_proc_node *Next;
@ -286,7 +288,7 @@ static b32 S2_ObjectIsTrue(scene2_object Object);
static compiled_scene2 S2_CompiledFromString(arena *Arena, string String);
static compiled_scene2 S2_CopyCompiledScene(arena *Arena, compiled_scene2 *Source);
static void S2_SetCurrentProc(scene2_runtime *Runtime, scene2_proc_info *Info);
static void S2_SetCurrentProc(scene2_runtime *Runtime, scene2_proc_info Info);
static scene2_proc_info S2_ProcFromName(compiled_scene2 *Compiled, string Name);
#endif //VN_SCENE2_H

View File

@ -77,6 +77,11 @@
{ ctr_set_talking, S2_Call_CharacterSetTalking, "makes a character talking" },
{ ctr_unset_all_talking, S2_Call_CharacterUnsetAllTalking, "makes no characters talking" },
// sixten: nav management calls
{ nav_load, S2_Call_NavLoad, "loads a nav scene" },
// sixten: puzzle management calls
{ puzzle_15, S2_Call_Puzzle15, "plays the 15-puzzle" },
}
@table_gen

View File

@ -135,9 +135,9 @@ static S2_CALL_FUNCTION(S2_Call_CharacterRemove)
string Target = TargetObject.As.String;
scene_view_character_data *CharacterBegin = SceneView->Characters;
scene_view_character_data *CharacterEnd = SceneView->Characters+SceneView->CharactersUsed;
scene_view_character_data *Character = CharacterBegin;
scene_view_character_data *CharacterBegin = SceneView->Characters;
scene_view_character_data *CharacterEnd = SceneView->Characters+SceneView->CharactersUsed;
scene_view_character_data *Character = CharacterBegin;
// sixten: check if the character exists
for(;Character < CharacterEnd; Character += 1)
@ -200,3 +200,60 @@ static S2_CALL_FUNCTION(S2_Call_CharacterUnsetAllTalking)
Character->Talking = false;
}
}
static void SV_LoadNavItems(string FileName);
static S2_CALL_FUNCTION(S2_Call_NavLoad)
{
scene2_object Object = S2_StackPop(Runtime);
if(Object.Kind == S2_ObjectKind_String)
{
SV_LoadNavItems(Object.As.String);
}
}
static S2_CALL_FUNCTION(S2_Call_Puzzle15)
{
scene_view *SceneView = (scene_view *)Runtime->Data;
SceneView->Mode = SV_Mode_P15;
SceneView->BoardOpenT = 0;
SceneView->TimeSinceBoardUpdate = 0;
SceneView->TimeSinceBoardClear = 0;
SceneView->BoardIsComplete = false;
// sixten: generate random board
for(s32 BoardY = 0; BoardY < 4; BoardY += 1)
{
for(s32 BoardX = 0; BoardX < 4; BoardX += 1)
{
SceneView->Board[BoardY][BoardX] = (1+BoardX+BoardY*4)%16;
}
}
v2_s32 EmptyP = V2S32(3, 3);
s32 ShuffleCount = 10000;
for(s32 Index = 0; Index < ShuffleCount; Index += 1)
{
s32 DeltaX = (rand() % 2)*2-1;
s32 DeltaY = (rand() % 2)*2-1;
// sixten: apply x-action
s32 NewEmptyX = EmptyP.x+DeltaX;
if(0 <= NewEmptyX && NewEmptyX < 4)
{
SceneView->Board[EmptyP.y][EmptyP.x] = SceneView->Board[EmptyP.y][NewEmptyX];
SceneView->Board[EmptyP.y][NewEmptyX] = 0;
EmptyP.x = NewEmptyX;
}
// sixten: apply y-action
s32 NewEmptyY = EmptyP.y+DeltaY;
if(0 <= NewEmptyY && NewEmptyY < 4)
{
SceneView->Board[EmptyP.y][EmptyP.x] = SceneView->Board[NewEmptyY][EmptyP.x];
SceneView->Board[NewEmptyY][EmptyP.x] = 0;
EmptyP.y = NewEmptyY;
}
}
Copy(SceneView->PrevBoard, SceneView->Board, sizeof(SceneView->Board));
}

View File

@ -27,12 +27,11 @@ static void SV_Reset(void)
SceneView->CharactersUsed = 0;
}
static void SV_LoadNavItems(void)
static void SV_LoadNavItems(string FileName)
{
#if 0
scene_view *SceneView = SV_GetState();
temp Scratch = GetScratch();
string NavData = Platform_ReadEntireFile(Scratch.Arena, SceneView->Runtime.Compiled.NavFileName);
string NavData = Platform_ReadEntireFile(Scratch.Arena, FileName);
if(NavData.Count != 0)
{
@ -114,7 +113,6 @@ static void SV_LoadNavItems(void)
}
}
ReleaseScratch(Scratch);
#endif
}
static void SV_SetCurrentSource(compiled_scene2 *Compiled)
@ -128,10 +126,6 @@ static void SV_SetCurrentSource(compiled_scene2 *Compiled)
ArenaClear(SceneView->SceneArena);
SceneView->Compiled = S2_CopyCompiledScene(SceneView->SceneArena, Compiled);
SV_LoadNavItems();
//- sixten: find main proc
S2_SetCurrentProc(Runtime, S2_ProcFromName(Compiled, StrLit("main")));
}
@ -494,219 +488,250 @@ static ui_signal BuildNavItemAndLabel(scene_nav_item *Item, r32 GlobalScale, v2_
return(Signal);
}
static void BuildNavView(scene_view *View, ui_box *Box, v2_r32 BoxDim)
static UI_CUSTOM_DRAW_CALLBACK(Puzzle15DrawCallback)
{
r32 GlobalScale = CalculateGlobalScaleFromDim(BoxDim);
scene_view *SceneView = (scene_view *)Data;
render_handle Texture = A_TextureFromAssetID(AssetID_Duck);
v2_r32 TextureDim = ConvertV2ToR32(DimFromTexture(Texture));
v2_r32 PieceDim = DimOfRange(Box->Rect)*0.25f;
v2_r32 Offset = Box->Rect.Min+V2R32(0, (1.0f - SceneView->BoardOpenT)*PieceDim.y);
if(SceneView->TimeSinceBoardClear < 2)
{
for(s32 BoardY = 0; BoardY < 4; BoardY += 1)
{
for(s32 BoardX = 0; BoardX < 4; BoardX += 1)
{
v2_r32 SourceDim = TextureDim*0.25f;
u8 BoardValue = SceneView->Board[BoardY][BoardX];
if(BoardValue)
{
s32 PrevBoardX = BoardX;
s32 PrevBoardY = BoardY;
if(SceneView->PrevBoard[PrevBoardY][PrevBoardX] != BoardValue)
{
for(PrevBoardY = 0; PrevBoardY < 4; PrevBoardY += 1)
{
for(PrevBoardX = 0; PrevBoardX < 4; PrevBoardX += 1)
{
if(SceneView->PrevBoard[PrevBoardY][PrevBoardX] == BoardValue)
{
goto FoundPrevTile;
}
}
}
FoundPrevTile:;
}
for(int ItemIndex = 0; ItemIndex < View->NavItemCount; ++ItemIndex)
{
scene_nav_item *Item = View->NavItems+ItemIndex;
if(BuildNavItemAndLabel(Item, GlobalScale, BoxDim).Clicked)
{
// sixten: apply the action
if(Item->Action.Kind == S_NavAction_Proc)
{
S2_SetCurrentProc(&View->Runtime, S2_ProcFromName(&View->Compiled, Item->Action.Content));
}
else if(Item->Action.Kind == S_NavAction_Scene)
{
temp Scratch = GetScratch();
string Filepath = PushFormat(Scratch.Arena, "data/%S.vns", Item->Action.Content);;
BoardValue -= 1;
s32 SourceX = BoardValue % 4;
s32 SourceY = BoardValue / 4;
string SceneInput = Platform_ReadEntireFile(Scratch.Arena, Filepath);
compiled_scene2 Scene = S2_CompiledFromString(Scratch.Arena, SceneInput);
SV_SetCurrentSource(&Scene);
v2_r32 BoardP = LinearBlend(V2R32(PrevBoardX, PrevBoardY), V2R32(BoardX, BoardY), Clamp01(Pow(SceneView->TimeSinceBoardUpdate*5, 4)));
ReleaseScratch(Scratch);
}
}
}
range2_r32 Source = Range2R32(V2R32(SourceX*SourceDim.x, SourceY*SourceDim.y), V2R32((SourceX+1)*SourceDim.x, (SourceY+1)*SourceDim.y));
range2_r32 Dest = Range2R32(Offset+BoardP*PieceDim, Offset+(BoardP+V2R32(1, 1))*PieceDim);
v4_r32 Color = SetAlpha(Color_White, SceneView->BoardOpenT);
PushTexturedQuad(Group, Dest, Source, Color, Color, Color, Color, 3, 3, 3, 3, 1.5f, 0, Texture);
}
}
}
}
if(SceneView->BoardIsComplete)
{
r32 CompleteT = Clamp01(Pow(SceneView->TimeSinceBoardClear, 5))*Clamp01(3-SceneView->TimeSinceBoardClear);
range2_r32 Source = Range2R32(V2R32(0, 0), TextureDim);
range2_r32 Dest = Pad(Box->Rect, PieceDim*(1.0f-CompleteT));
v4_r32 Color = SetAlpha(Color_White, CompleteT);
PushTexturedQuad(Group, Dest, Source, Color, Color, Color, Color, 3, 3, 3, 3, 1.5f, 0, Texture);
}
}
static void BuildScene(scene_view *View)
static void BuildScene(scene_view *SceneView)
{
v2_r32 ParentDim = UI_CalculateBoxDim(UI_TopParent());
v2_r32 ParentDim = UI_CalculateBoxDim(UI_TopParent());
r32 TargetRatio = 16.0f/9.0f;
r32 ActualRatio = ParentDim.x/ParentDim.y;
r32 TargetRatio = 16.0f/9.0f;
r32 ActualRatio = ParentDim.x/ParentDim.y;
v2_r32 BoxDim = ParentDim;
v2_r32 BoxDim = ParentDim;
if(ActualRatio>TargetRatio)
{
BoxDim.x = BoxDim.y*TargetRatio;
}
else
{
BoxDim.y = BoxDim.x/TargetRatio;
}
if(ActualRatio > TargetRatio)
{
BoxDim.x = BoxDim.y*TargetRatio;
}
else
{
BoxDim.y = BoxDim.x/TargetRatio;
}
UI_SetNextWidth(UI_Pixels(BoxDim.x, 1));
UI_SetNextHeight(UI_Pixels(BoxDim.y, 1));
UI_SetNextLayoutAxis(Axis2_Y);
UI_SetNextFixedP((ParentDim-BoxDim)*0.5f);
ui_box *Box = UI_MakeBox(UI_BoxFlag_Clip|UI_BoxFlag_DrawDropShadow|UI_BoxFlag_FloatingX|UI_BoxFlag_FloatingY, StrLit("Scene View"));
UI_EquipBoxCustomDrawCallback(Box, BuildSceneDrawCallback, View);
UI_SetNextWidth(UI_Pixels(BoxDim.x, 1));
UI_SetNextHeight(UI_Pixels(BoxDim.y, 1));
UI_SetNextLayoutAxis(Axis2_Y);
UI_SetNextFixedP((ParentDim-BoxDim)*0.5f);
ui_box *Box = UI_MakeBox(UI_BoxFlag_Clip|UI_BoxFlag_DrawDropShadow|UI_BoxFlag_FloatingX|UI_BoxFlag_FloatingY, StrLit("Scene View"));
UI_EquipBoxCustomDrawCallback(Box, BuildSceneDrawCallback, SceneView);
UI_Parent(Box)
{
if(SV_CurrentlyInProc())
{
BuildProcView(View, Box, BoxDim);
}
else
{
BuildNavView(View, Box, BoxDim);
}
}
r32 GlobalScale = CalculateGlobalScaleFromDim(BoxDim);
UI_Parent(Box)
{
switch(SceneView->Mode)
{
case SV_Mode_Scene:
{
// sixten(NOTE): when this is rewritten, put it inside THIS function.
BuildProcView(SceneView, Box, BoxDim);
} break;
case SV_Mode_Nav:
{
for(int ItemIndex = 0; ItemIndex < SceneView->NavItemCount; ++ItemIndex)
{
scene_nav_item *Item = SceneView->NavItems+ItemIndex;
if(BuildNavItemAndLabel(Item, GlobalScale, BoxDim).Clicked)
{
// sixten: apply the action
if(Item->Action.Kind == S_NavAction_Proc)
{
S2_SetCurrentProc(&SceneView->Runtime, S2_ProcFromName(&SceneView->Compiled, Item->Action.Content));
}
else if(Item->Action.Kind == S_NavAction_Scene)
{
temp Scratch = GetScratch();
string Filepath = PushFormat(Scratch.Arena, "data/%S.vns", Item->Action.Content);;
string SceneInput = Platform_ReadEntireFile(Scratch.Arena, Filepath);
compiled_scene2 Scene = S2_CompiledFromString(Scratch.Arena, SceneInput);
SV_SetCurrentSource(&Scene);
ReleaseScratch(Scratch);
}
}
}
} break;
case SV_Mode_P15:
{
UI_WidthFill UI_HeightFill UI_BackgroundColor(SetAlpha(Color_Black, 0.5*SceneView->BoardOpenT*Clamp01(2-SceneView->TimeSinceBoardClear*0.5))) UI_LayoutAxis(Axis2_X)
UI_Parent(UI_MakeBox(UI_BoxFlag_DrawBackground, StrLit("15 Puzzle Darken")))
{
UI_Padding(UI_Percent(1, 0)) UI_Width(UI_ChildrenSum(1, 1)) UI_Column() UI_Padding(UI_Percent(1, 0))
{
UI_SetNextSize(UI_Em(25, 1), UI_Em(25, 1));
ui_box *PuzzleBox = UI_MakeBox(0, StrLit("Puzzle Box"));
UI_EquipBoxCustomDrawCallback(PuzzleBox, Puzzle15DrawCallback, SceneView);
}
}
} break;
}
}
}
static void BuildErrorScreen(scene_view *SceneView, vn_input *Input)
{
UI_SetNextLayoutAxis(Axis2_X);
UI_Parent(UI_MakeBox(UI_BoxFlag_DrawBackground, StrLit("Container")))
{
UI_Padding(UI_Em(3, 1)) UI_Width(UI_Percent(1, 0)) UI_Column() UI_Padding(UI_Em(3, 1))
{
UI_Font(Font_Bold) UI_Size(UI_TextContent(0, 1), UI_TextContent(0, 1)) UI_FontSize(32) UI_LabelF("A runtime error has occurred");
s64 ErrorIndex = 0;
UI_SetNextLayoutAxis(Axis2_X);
UI_Parent(UI_MakeBox(UI_BoxFlag_DrawBackground, StrLit("Container")))
{
UI_Padding(UI_Em(3, 1)) UI_Width(UI_Percent(1, 0)) UI_Column() UI_Padding(UI_Em(3, 1))
{
UI_Font(Font_Bold) UI_Size(UI_TextContent(0, 1), UI_TextContent(0, 1)) UI_FontSize(32) UI_LabelF("A runtime error has occurred");
s64 ErrorIndex = 0;
for(scene2_message *Message = SceneView->Messages.First; Message != 0; Message = Message->Next, ErrorIndex += 1)
{
UI_Spacer(UI_Em(3, 1));
UI_SetNextCornerRadius(3);
UI_Size(UI_Percent(1, 1), UI_Percent(1, 0)) UI_Parent(UI_MakeBoxF(UI_BoxFlag_DrawDropShadow|UI_BoxFlag_DrawBorder, "%i", ErrorIndex))
UI_Size(UI_TextContent(30, 1), UI_TextContent(30, 1))
{
{
UI_Spacer(UI_Em(3, 1));
UI_SetNextCornerRadius(3);
UI_Size(UI_Percent(1, 1), UI_Percent(1, 0)) UI_Parent(UI_MakeBoxF(UI_BoxFlag_DrawDropShadow|UI_BoxFlag_DrawBorder, "%i", ErrorIndex))
UI_Size(UI_TextContent(30, 1), UI_TextContent(30, 1))
{
UI_Label(Message->Message);
}
}
UI_Spacer(UI_Em(3, 1));
UI_Size(UI_Percent(1, 1), UI_Em(2, 1)) UI_Row()
UI_Width(UI_TextContent(30, 1)) UI_CornerRadius(4)
{
ui_signal IgnoreSignal = UI_ButtonF("Ignore");
if(IgnoreSignal.Hovering)
{
UI_TooltipLabel(StrLit("Continue running the script, may lead to more errors."), UI_MouseP());
}
if(IgnoreSignal.Clicked)
{
}
}
UI_Spacer(UI_Em(3, 1));
UI_Size(UI_Percent(1, 1), UI_Em(2, 1)) UI_Row()
UI_Width(UI_TextContent(30, 1)) UI_CornerRadius(4)
{
ui_signal IgnoreSignal = UI_ButtonF("Ignore");
if(IgnoreSignal.Hovering)
{
UI_TooltipLabel(StrLit("Continue running the script, may lead to more errors."), UI_MouseP());
}
if(IgnoreSignal.Clicked)
{
ZeroStruct(&SceneView->Messages);
ArenaClear(SceneView->MessageArena);
}
}
UI_Spacer(UI_Em(1, 1));
UI_Spacer(UI_Em(1, 1));
ui_signal RestartSignal = UI_ButtonF("Restart");
if(RestartSignal.Hovering)
{
UI_TooltipLabel(StrLit("Restarts the script, may lose progress."), UI_MouseP());
}
if(RestartSignal.Clicked)
{
SV_Reset();
}
ui_signal RestartSignal = UI_ButtonF("Restart");
if(RestartSignal.Hovering)
{
UI_TooltipLabel(StrLit("Restarts the script, may lose progress."), UI_MouseP());
}
if(RestartSignal.Clicked)
{
SV_Reset();
}
UI_Spacer(UI_Em(1, 1));
if(UI_ButtonF("Exit Program").Clicked)
{
Input->ExitRequested = true;
}
}
}
}
UI_Spacer(UI_Em(1, 1));
if(UI_ButtonF("Exit Program").Clicked)
{
Input->ExitRequested = true;
}
}
}
}
}
static scene_view_character_data *SV_CharacterDataFromName(string Name)
{
scene_view_character_data *Result = 0;
scene_view_character_data *Result = 0;
scene_view *View = SV_GetState();
scene_view *View = SV_GetState();
for(s32 CharacterIndex = 0; CharacterIndex < View->CharactersUsed; CharacterIndex += 1)
{
scene_view_character_data *Character = View->Characters + CharacterIndex;
if(AreEqual(Character->Name, Name))
{
Result = Character;
break;
}
}
for(s32 CharacterIndex = 0; CharacterIndex < View->CharactersUsed; CharacterIndex += 1)
{
scene_view_character_data *Character = View->Characters + CharacterIndex;
if(AreEqual(Character->Name, Name))
{
Result = Character;
break;
}
}
//- sixten: create character if not initialized
if(!Result && View->CharactersUsed < ArrayCount(View->Characters))
{
s32 CharacterIndex = View->CharactersUsed;
View->CharactersUsed += 1;
//- sixten: create character if not initialized
if(!Result && View->CharactersUsed < ArrayCount(View->Characters))
{
s32 CharacterIndex = View->CharactersUsed;
View->CharactersUsed += 1;
Result = View->Characters + CharacterIndex;
*Result = {};
Result->Name = Name;
Result->Active = true;
Result->PctP = (r32)(CharacterIndex + 1) / (View->CharactersUsed + 1);
}
Result = View->Characters + CharacterIndex;
*Result = {};
Result->Name = Name;
Result->Active = true;
Result->PctP = (r32)(CharacterIndex + 1) / (View->CharactersUsed + 1);
}
return(Result);
return(Result);
}
#if 0
static scene_view_character_texture_info SV_CharacterTextureFromAction(scene_character_action *Action)
{
scene_view_character_texture_info Result = {};
Result.Texture = EmptyRenderHandle();
Result.Scale = 1.0f;
asset_id AssetID = Action->State;
Result.Texture = A_TextureFromAssetID(AssetID);
Result.Scale = A_ScaleFromAssetID(AssetID);
#if 0
if(AreEqual(StrLit("arthur"), Action->Target))
{
switch(Action->State)
{
case CR_State_Normal: { Result.Texture = View->TestNormal; } break;
case CR_State_Happy: { Result.Texture = View->TestHappy; } break;
default: break;
}
Result.Scale = 0.017f;
}
else if(AreEqual(StrLit("monika"), Action->Target))
{
switch(Action->State)
{
case CR_State_Leaning: { Result.Texture = View->MonikaLeaning; } break;
default: break;
}
Result.Scale = 0.033f;
}
#endif
return(Result);
}
#endif
static r32 SV_CalculateTargetPctP(s32 TrueCharacterIndex)
{
scene_view *View = SV_GetState();
s32 CharacterCount = 0;
s32 AssumedCharacterIndex = 0;
for(s32 CharacterIndex = 0; CharacterIndex < View->CharactersUsed; CharacterIndex += 1)
{
scene_view_character_data *Data = View->Characters + CharacterIndex;
if(Data->Active)
{
CharacterCount += 1;
if(CharacterIndex < TrueCharacterIndex)
{
AssumedCharacterIndex += 1;
}
}
}
r32 Result = (r32)(AssumedCharacterIndex + 1) / (Max(CharacterCount, 1) + 1);
return(Result);
scene_view *View = SV_GetState();
s32 CharacterCount = 0;
s32 AssumedCharacterIndex = 0;
for(s32 CharacterIndex = 0; CharacterIndex < View->CharactersUsed; CharacterIndex += 1)
{
scene_view_character_data *Data = View->Characters + CharacterIndex;
if(Data->Active)
{
CharacterCount += 1;
if(CharacterIndex < TrueCharacterIndex)
{
AssumedCharacterIndex += 1;
}
}
}
r32 Result = (r32)(AssumedCharacterIndex + 1) / (Max(CharacterCount, 1) + 1);
return(Result);
}
static void SV_UpdateInDialog(arena *FrameArena)
@ -870,34 +895,34 @@ static void SV_UpdateInDialog(arena *FrameArena)
static void SV_Update(arena *FrameArena)
{
scene_view *SceneView = SV_GetState();
scene_view *SceneView = SV_GetState();
//- sixten: update the characters
{
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharactersUsed; CharacterIndex += 1)
{
scene_view_character_data *Data = SceneView->Characters + CharacterIndex;
//- sixten: update the characters
{
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharactersUsed; CharacterIndex += 1)
{
scene_view_character_data *Data = SceneView->Characters + CharacterIndex;
if(!SV_CurrentlyInProc())
{
Data->Active = false;
Data->Talking = false;
}
if(!SV_CurrentlyInProc())
{
Data->Active = false;
Data->Talking = false;
}
AC_AnimateValueDirect(Data->Active, 0.5f, &Data->ActiveT);
AC_AnimateValueDirect(Data->Talking, 0.4f, &Data->TalkingT);
AC_AnimateValueDirect(Data->Active, 0.5f, &Data->ActiveT);
AC_AnimateValueDirect(Data->Talking, 0.4f, &Data->TalkingT);
r32 TargetPctP;
if(Data->Active)
{
TargetPctP = SV_CalculateTargetPctP(CharacterIndex);
}
else
{
TargetPctP = (r32)(CharacterIndex+1)/(SceneView->CharactersUsed+1);
}
AC_AnimateValueDirect(TargetPctP, 0.4f, &Data->PctP);
}
r32 TargetPctP;
if(Data->Active)
{
TargetPctP = SV_CalculateTargetPctP(CharacterIndex);
}
else
{
TargetPctP = (r32)(CharacterIndex+1)/(SceneView->CharactersUsed+1);
}
AC_AnimateValueDirect(TargetPctP, 0.4f, &Data->PctP);
}
// sixten: prune any unactive characters
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharactersUsed; CharacterIndex += 1)
@ -910,13 +935,144 @@ static void SV_Update(arena *FrameArena)
CharacterIndex -= 1;
}
}
}
}
//- sixten: update scene
if(SV_CurrentlyInProc())
{
SV_UpdateInDialog(FrameArena);
}
// sixten(HACK): if a scene has been triggered, switch mode
if(SceneView->Mode == SV_Mode_Nav && SV_CurrentlyInProc())
{
SceneView->Mode = SV_Mode_Scene;
}
switch(SceneView->Mode)
{
case SV_Mode_Scene:
{
//- sixten: gather user input
b32 MousePressed = false;
for(platform_event *Event = SceneView->EventList->First; Event != 0; Event = Event->Next)
{
if(Event->Type == PlatformEvent_Press && Event->Key == Key_MouseLeft)
{
MousePressed = true;
}
}
b32 PlayerAction = (Platform_KeyPress(SceneView->EventList, Key_Space)||MousePressed);
//- sixten: check if we can skip the current textbox
if(PlayerAction && SceneView->TextboxRevealed < SceneView->TextboxUsed)
{
PlayerAction = false;
SceneView->TextboxRevealed = SceneView->TextboxUsed;
}
//- sixten: update the textbox
r32 CharsPerSecond = 25.0f;
SceneView->TextboxRevealed = Min((r32)SceneView->TextboxUsed, SceneView->TextboxRevealed+CharsPerSecond*SceneView->dtForFrame);
//- sixten: run the runtime
scene2_run_result RunResult = S2_Run(FrameArena, &SceneView->Runtime, &SceneView->Compiled, PlayerAction);
//- sixten: append messages
S2_ConcatMessageList(SceneView->MessageArena, &SceneView->Messages, &RunResult.Messages);
for(scene2_action *Action = RunResult.Actions.First; Action != 0; Action = Action->Next)
{
switch(Action->Kind)
{
case S2_ActionKind_None: { InvalidCodepath; } break;
InvalidDefaultCase;
}
}
// sixten: check if the scene is finished
if(!SV_CurrentlyInProc() && SceneView->Mode == SV_Mode_Scene)
{
SceneView->Mode = SV_Mode_Nav;
}
} break;
case SV_Mode_Nav:
{
} break;
case SV_Mode_P15:
{
SceneView->TimeSinceBoardUpdate += SceneView->dtForFrame;
AC_AnimateValueDirect(1, 2.0f, &SceneView->BoardOpenT);
if(SceneView->BoardIsComplete)
{
SceneView->TimeSinceBoardClear += SceneView->dtForFrame;
if(SceneView->TimeSinceBoardClear > 3.5f)
{
SceneView->Mode = SV_Mode_Scene;
}
}
else
{
v2_s32 BoardDelta = V2S32(0, 0);
if(Platform_KeyPress(SceneView->EventList, Key_Up)) { BoardDelta.y += 1; }
if(Platform_KeyPress(SceneView->EventList, Key_Down)) { BoardDelta.y -= 1; }
if(Platform_KeyPress(SceneView->EventList, Key_Left)) { BoardDelta.x += 1; }
if(Platform_KeyPress(SceneView->EventList, Key_Right)) { BoardDelta.x -= 1; }
if(BoardDelta.x != 0 || BoardDelta.y != 0)
{
if(BoardDelta.x && BoardDelta.y)
{
BoardDelta.y = 0;
}
// sixten: find the current empty square
v2_s32 EmptyP = V2S32(-10, -10);
for(s32 BoardY = 0; BoardY < 4; BoardY += 1)
{
for(s32 BoardX = 0; BoardX < 4; BoardX += 1)
{
if(SceneView->Board[BoardY][BoardX] == 0)
{
EmptyP = V2S32(BoardX, BoardY);
goto FoundEmptyP;
}
}
}
FoundEmptyP:;
// sixten: check if we are able to perform an action
range2_s32 BoardRange = Range2S32(V2S32(0, 0), V2S32(4, 4));
v2_s32 NewEmptyP = EmptyP+BoardDelta;
if(InRange(BoardRange, NewEmptyP))
{
SceneView->TimeSinceBoardUpdate = 0;
Copy(SceneView->PrevBoard, SceneView->Board, sizeof(SceneView->Board));
SceneView->Board[EmptyP.y][EmptyP.x] = SceneView->Board[NewEmptyP.y][NewEmptyP.x];
SceneView->Board[NewEmptyP.y][NewEmptyP.x] = 0;
}
// sixten: check if board is completed
b32 BoardIsComplete = true;
for(s32 BoardY = 0; BoardY < 4; BoardY += 1)
{
for(s32 BoardX = 0; BoardX < 4; BoardX += 1)
{
if(SceneView->Board[BoardY][BoardX] != (1+BoardX+BoardY*4)%16)
{
BoardIsComplete = false;
goto BoardNotComplete;
}
}
}
BoardNotComplete:;
if(BoardIsComplete)
{
SceneView->BoardIsComplete = true;
}
}
}
} break;
}
}
static void SV_BuildSceneView(vn_input *Input)
@ -931,17 +1087,3 @@ static void SV_BuildSceneView(vn_input *Input)
BuildScene(SceneView);
}
}
#if 0
scene_user_input Input = SV_GatherInputs(); // note that we here could consume a player interaction for skipping the text
scene_runtime_result Result = S_Run(&Runtime, &Inputs);
for(scene_action *Action = Result.FirstAction; Action != 0; Action = Action->Next)
{
switch(Action->Kind)
{
...
}
}
#endif

View File

@ -66,6 +66,13 @@ struct scene_nav
s32 ItemMax;
};
enum scene_view_mode
{
SV_Mode_Scene,
SV_Mode_Nav,
SV_Mode_P15,
};
struct scene_view
{
arena *SceneArena;
@ -73,6 +80,7 @@ struct scene_view
//- sixten: state
scene2_runtime Runtime;
compiled_scene2 Compiled;
scene_view_mode Mode;
//- sixten: messages
arena *MessageArena;
@ -94,6 +102,14 @@ struct scene_view
//- sixten: input per frame
platform_event_list *EventList;
r32 dtForFrame;
//- sixten: 15-puzzle
r32 BoardOpenT;
u8 Board[4][4];
u8 PrevBoard[4][4];
b32 BoardIsComplete;
r32 TimeSinceBoardUpdate;
r32 TimeSinceBoardClear;
};
static void SV_SetState(scene_view *View);

View File

@ -273,12 +273,12 @@ static void W_BuildTabItem(workspace_panel *Panel, workspace_view *View)
UI_SetNextWidth(UI_ChildrenSum(1, 1));
UI_SetNextHeight(UI_Percent(1, 1));
UI_SetNextBackgroundColor(Brighten(BackgroundColor, 1.2f));
UI_SetNextBorderColor(LinearBlend(UI_TopBackgroundColor(), Color_Grey, 0.5));
UI_SetNextBorderColor(Darken(LinearBlend(UI_TopBackgroundColor(), Color_White, 0.2f), 1.2f));
UI_SetNextLayoutAxis(Axis2_X);
UI_SetNextCornerRadii(V4R32(3.0, 3.0, 0, 0));
UI_SetNextCornerRadii(V4R32(5.0, 5.0, 0, 0));
ui_box *TabBox = UI_MakeBoxF(UI_BoxFlag_DrawBackground |
//UI_BoxFlag_DrawBorder |
UI_BoxFlag_DrawBorder |
UI_BoxFlag_DrawDropShadow |
UI_BoxFlag_HotAnimation |
UI_BoxFlag_ActiveAnimation |

View File

@ -240,12 +240,6 @@ static void W_BuildNavEditor(workspace_view *View)
{
W_NavEditorSerializeItems(Editor);
}
//- sixten: create force reload
if(UI_ButtonF("%U", FontIcon_ArrowsCW).Clicked)
{
SV_LoadNavItems();
}
}
}

Binary file not shown.

BIN
data/omori.vnn 100644

Binary file not shown.

34
data/omori.vns 100644
View File

@ -0,0 +1,34 @@
proc main
call nav_load("data/omori.vnn")
call proc_set("omori_1")
end
proc omori_1
s = "Sunny"
$(s) "There is something I have to tell you."
$(s) "It's about MARI."
$(s) "..."
$(s) "She didn't kill herself."
$(s) "It was the day of the recital."
$(s) "We had been rehearsing for hours, but no matter how much time we spent it was never good enough."
$(s) "I had just messed up a note when in my anger I stormed out."
$(s) "MARI was quick to follow me, just in time to see me throw the violin to the ground."
$(s) "We were at the top of the stairs when she finally managed to grab my arm."
$(s) "She was so calm... Not mad at all... Just disappointed."
$(s) "But I didn't want to be there. I didn't want her to be there. I just wanted to go away."
$(s) "Before I was able to run away again, she blocked my path and without thinking I pushed and..."
$(s) "...she fell."
$(s) "She fell down the stairs."
$(s) "That same day, BASIL happened to be visiting."
$(s) "He couldn't believe what he saw and in order to protect me..."
$(s) "...he and I staged MARI's suicide."
end
proc puzzle_test
$ "Can you beat the IMPOSSIBLE duck puzzle?"
call puzzle_15()
$ "Wow, you actually did it."
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 569 KiB