aboutsummaryrefslogtreecommitdiffstats
path: root/Game/Code/Classes
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--Game/Code/Classes/TextGL.pas106
-rw-r--r--Game/Code/Classes/UDraw.pas367
-rw-r--r--Game/Code/Classes/UFiles.pas2
-rw-r--r--Game/Code/Classes/UIni.pas15
-rw-r--r--Game/Code/Classes/UMain.pas518
-rw-r--r--Game/Code/Classes/UMusic.pas51
-rw-r--r--Game/Code/Classes/UParty.pas6
-rw-r--r--Game/Code/Classes/USingScores.pas18
8 files changed, 580 insertions, 503 deletions
diff --git a/Game/Code/Classes/TextGL.pas b/Game/Code/Classes/TextGL.pas
index b21a5237..1396ae1b 100644
--- a/Game/Code/Classes/TextGL.pas
+++ b/Game/Code/Classes/TextGL.pas
@@ -20,23 +20,24 @@ uses
SDL_ttf,
ULog;
-procedure BuildFont; // Build Our Bitmap Font
-procedure KillFont; // Delete The Font
-function glTextWidth(text: pchar): real; // Returns Text Width
+procedure BuildFont; // build our bitmap font
+procedure KillFont; // delete the font
+function glTextWidth(text: pchar): real; // returns text width
procedure glPrintDone(text: pchar; Done: real; ColR, ColG, ColB: real);
procedure glPrintLetter(letter: char);
procedure glPrintLetterCut(letter: char; Start, Finish: real);
-procedure glPrint(text: pchar); // Custom GL "Print" Routine
+procedure glPrint(text: pchar); // custom GL "Print" routine
procedure glPrintCut(text: pchar);
-procedure SetFontPos(X, Y: real); // Sets X And Y
+procedure SetFontPos(X, Y: real); // sets X and Y
procedure SetFontSize(Size: real);
-procedure SetFontStyle(Style: integer); // sets active font style (normal, bold, etc)
-procedure SetFontItalic(Enable: boolean); // sets italic type letter (works for all fonts)
+procedure SetFontStyle(Style: integer); // sets active font style (normal, bold, etc)
+procedure SetFontItalic(Enable: boolean); // sets italic type letter (works for all fonts)
procedure SetFontAspectW(Aspect: real);
procedure SetFontReflection(Enable:boolean;Spacing: real); // Enables/Disables text reflection
+
// Start of SDL_ttf
function NextPowerOfTwo(Value: integer): integer;
-//Checks if the ttf exists, if yes then a SDL_ttf is returned
+// Checks if the ttf exists, if yes then a SDL_ttf is returned
function LoadFont(FileName: PAnsiChar; PointSize: integer):PTTF_Font;
// Does the renderstuff, color is in $ffeecc style
@@ -69,7 +70,7 @@ type
var
- base: GLuint; // Base Display List For The Font Set
+ base: GLuint; // base display list for the font set
Fonts: array of TFont;
ActFont: integer;
PColR: real; // temps for glPrintDone
@@ -79,6 +80,7 @@ var
// Colours for the reflection
TempColor: array[0..3] of GLfloat;
PTempColor: PGLfloat;
+
implementation
uses
@@ -87,26 +89,26 @@ uses
SysUtils,
UGraphic;
-procedure BuildFont; // Build Our Bitmap Font
-
- procedure loadfont(aID : integer; const aType, aResourceName: string);
- var
- stream: TStream;
+procedure LoadBitmapFontInfo(aID : integer; const aType, aResourceName: string);
+var
+ stream: TStream;
+begin
+ stream := GetResourceStream(aResourceName, aType);
+ if (not assigned(stream)) then
begin
- stream := GetResourceStream(aResourceName, aType);
- if (not assigned(stream)) then
- begin
- Log.LogError('Unknown font['+ inttostr(aID) +': '+aType+']', 'loadfont');
- Exit;
- end;
- try
- stream.Read(Fonts[ aID ].Width, 256);
- except
- Log.LogError('Error while reading font['+ inttostr(aID) +': '+aType+']', 'loadfont');
- end;
- stream.Free;
+ Log.LogError('Unknown font['+ inttostr(aID) +': '+aType+']', 'loadfont');
+ Exit;
end;
+ try
+ stream.Read(Fonts[ aID ].Width, 256);
+ except
+ Log.LogError('Error while reading font['+ inttostr(aID) +': '+aType+']', 'loadfont');
+ end;
+ stream.Free;
+end;
+// Builds bitmap fonts
+procedure BuildFont;
var
Count: integer;
begin
@@ -150,16 +152,11 @@ begin
Fonts[4].Done := -1;
Fonts[4].Outline := 5;}
-
-
- loadfont( 0, 'FNT', 'Font' );
- loadfont( 1, 'FNT', 'FontB' );
- loadfont( 2, 'FNT', 'FontO' );
- loadfont( 3, 'FNT', 'FontO2' );
-
-{ Reg := TResourceStream.Create(HInstance, 'FontO', 'FNT');
- Reg.Read(Fonts[4].Width, 256);
- Reg.Free;}
+ // load font info
+ LoadBitmapFontInfo( 0, 'FNT', 'Font' );
+ LoadBitmapFontInfo( 1, 'FNT', 'FontB' );
+ LoadBitmapFontInfo( 2, 'FNT', 'FontO' );
+ LoadBitmapFontInfo( 3, 'FNT', 'FontO2' );
for Count := 0 to 255 do
Fonts[1].Width[Count] := Fonts[1].Width[Count] div 2;
@@ -175,9 +172,11 @@ begin
end;
-procedure KillFont; // Delete The Font
+// Deletes the font
+procedure KillFont;
begin
-// glDeleteLists(base, 256); // Delete All 96 Characters
+ // delete all characters
+ //glDeleteLists(base, 256);
end;
function glTextWidth(text: pchar): real;
@@ -185,13 +184,10 @@ var
Letter: char;
i: integer;
begin
-// Log.LogStatus(Text, 'glTextWidth');
Result := 0;
- for i := 0 to Length(text) -1 do // Patched by AlexanderS : bug with wrong sliced text lines
+ for i := 0 to Length(text) -1 do
begin
Letter := Text[i];
- // Bugfix: does not work with FPC, probably because a part of text is assigned to itself
- //text := pchar(Copy(text, 2, Length(text)-1));
Result := Result + Fonts[ActFont].Width[Ord(Letter)] * Fonts[ActFont].Tex.H / 30 * Fonts[ActFont].AspectW;
end;
end;
@@ -316,7 +312,7 @@ begin
FWidth := Fonts[ActFont].Width[Ord(Letter)];
W := FWidth * (H/30) * Fonts[ActFont].AspectW;
-// H := 30;
+ //H := 30;
OutTemp := Fonts[ActFont].Outline * (H/30) * Fonts[ActFont].AspectW;
// set texture positions
@@ -356,14 +352,14 @@ begin
end;
-procedure glPrint(text: pchar); // Custom GL "Print" Routine
+// Custom GL "Print" Routine
+procedure glPrint(text: pchar);
var
-// Letter : char;
+ //Letter : char;
iPos : integer;
-
begin
if (Text = '') then // If There's No Text
- Exit; // Do Nothing
+ Exit; // Do Nothing
(*
while (length(text) > 0) do
@@ -377,9 +373,9 @@ begin
end; // while
*)
-//Save the actual color and alpha (for reflection)
+ //Save the actual color and alpha (for reflection)
PTempColor:= @TempColor;
-//I've read that glGetFloat is quite slow, but it seems that there is no alternative
+ //I've read that glGetFloat is quite slow, but it seems that there is no alternative
glGetFloatv(GL_CURRENT_COLOR, PTempColor);
// This code is better, because doing a Copy of for every
@@ -393,9 +389,9 @@ begin
end;
-function NextPowerOfTwo(Value: integer): integer;
// tyty to Asphyre
// FIXME: check if the non-asm version is fast enough and use it by default if so
+function NextPowerOfTwo(Value: integer): integer;
begin
Result:= 1;
{$IF Defined(CPUX86_64)}
@@ -465,14 +461,14 @@ begin
clrbg.unused := 0;
sText := RenderText(font, 'katzeeeeeee', $fe198e);
-// sText := TTF_RenderText_Blended( font, 'huuuuuuuuuund', clrFG);
+ //sText := TTF_RenderText_Blended( font, 'huuuuuuuuuund', clrFG);
-// Convert the rendered text to a known format
+ // Convert the rendered text to a known format
w := nextpoweroftwo(sText.w);
h := nextpoweroftwo(sText.h);
intermediary := SDL_CreateRGBSurface(0, w, h, 32,
- $000000ff, $0000ff00, $00ff0000, $ff000000);
+ $000000ff, $0000ff00, $00ff0000, $ff000000);
SDL_SetAlpha(intermediary, 0, 255);
SDL_SetAlpha(sText, 0, 255);
@@ -518,8 +514,8 @@ var
PDoingNow: real;
S: string;
begin
- if (Text = '') then // If There's No Text
- Exit; // Do Nothing
+ if (Text = '') then // If There's No Text
+ Exit; // Do Nothing
PTotWidth := glTextWidth(Text);
PToDo := Fonts[ActFont].Done;
diff --git a/Game/Code/Classes/UDraw.pas b/Game/Code/Classes/UDraw.pas
index 53508baf..d82fef33 100644
--- a/Game/Code/Classes/UDraw.pas
+++ b/Game/Code/Classes/UDraw.pas
@@ -19,8 +19,8 @@ procedure SingDrawOscilloscope(X, Y, W, H: real; NrSound: integer);
procedure SingDrawNoteLines(Left, Top, Right: real; Space: integer);
procedure SingDrawBeatDelimeters(Left, Top, Right: real; NrLines: integer);
procedure SingDrawLine(Left, Top, Right: real; NrLines: integer; Space: integer);
-procedure SingDrawPlayerLine(X, Y, W: real; NrGracza: integer; Space: integer);
-procedure SingDrawPlayerBGLine(Left, Top, Right: real; NrLines, NrGracza: integer; Space: integer);
+procedure SingDrawPlayerLine(X, Y, W: real; PlayerIndex: integer; Space: integer);
+procedure SingDrawPlayerBGLine(Left, Top, Right: real; NrLines, PlayerIndex: integer; Space: integer);
// TimeBar
procedure SingDrawTimeBar();
@@ -338,129 +338,122 @@ end;
// draw sung notes
-procedure SingDrawPlayerLine(X, Y, W: real; NrGracza: integer; Space: integer);
+procedure SingDrawPlayerLine(X, Y, W: real; PlayerIndex: integer; Space: integer);
var
- TempR: real;
- Rec: TRecR;
- N: integer;
- R: real;
- G: real;
- B: real;
- A: real;
- NotesH2: real;
- begin
-// Log.LogStatus('Player notes', 'SingDraw');
+ TempR: real;
+ Rec: TRecR;
+ N: integer;
+ R, G, B, A: real;
+ NotesH2: real;
+begin
+ //Log.LogStatus('Player notes', 'SingDraw');
-// if NrGracza = 0 then LoadColor(R, G, B, 'P1Light')
-// else LoadColor(R, G, B, 'P2Light');
+ //if NrGracza = 0 then LoadColor(R, G, B, 'P1Light')
+ //else LoadColor(R, G, B, 'P2Light');
-// R := 71/255;
-// G := 175/255;
-// B := 247/255;
+ //R := 71/255;
+ //G := 175/255;
+ //B := 247/255;
glColor3f(1, 1, 1);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-//// if Player[NrGracza].IlNut > 0 then
+ //if Player[NrGracza].LengthNote > 0 then
+ begin
+ TempR := W / (Lines[0].Line[Lines[0].Current].End_ - Lines[0].Line[Lines[0].Current].Note[0].Start);
+ for N := 0 to Player[PlayerIndex].HighNote do
begin
- TempR := W / (Lines[0].Line[Lines[0].Current].End_ - Lines[0].Line[Lines[0].Current].Note[0].Start);
- for N := 0 to Player[NrGracza].HighNote do
+ with Player[PlayerIndex].Note[N] do
+ begin
+ // Left part of note
+ Rec.Left := X + (Start-Lines[0].Line[Lines[0].Current].Note[0].Start) * TempR + 0.5 + 10*ScreenX;
+ Rec.Right := Rec.Left + NotesW;
+
+ // Draw it in half size, if not hit
+ if Hit then
+ begin
+ NotesH2 := NotesH
+ end
+ else
+ begin
+ NotesH2 := int(NotesH * 0.65);
+ end;
+
+ Rec.Top := Y - (Tone-Lines[0].Line[Lines[0].Current].BaseNote)*Space/2 - NotesH2;
+ Rec.Bottom := Rec.Top + 2 *NotesH2;
+
+ // draw the left part
+ glColor3f(1, 1, 1);
+ glBindTexture(GL_TEXTURE_2D, Tex_Left[PlayerIndex+1].TexNum);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0, 0); glVertex2f(Rec.Left, Rec.Top);
+ glTexCoord2f(0, 1); glVertex2f(Rec.Left, Rec.Bottom);
+ glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom);
+ glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top);
+ glEnd;
+
+ // Middle part of the note
+ Rec.Left := Rec.Right;
+ Rec.Right := X + (Start+Length-Lines[0].Line[Lines[0].Current].Note[0].Start) * TempR - NotesW - 0.5 + 10*ScreenX;
+
+ // (nowe) - dunno
+ if (Start+Length-1 = LineState.CurrentBeatD) then
+ Rec.Right := Rec.Right - (1-Frac(LineState.MidBeatD)) * TempR;
+ // the left note is more right than the right note itself, sounds weird - so we fix that xD
+ if Rec.Right <= Rec.Left then
+ Rec.Right := Rec.Left;
+
+ // draw the middle part
+ glBindTexture(GL_TEXTURE_2D, Tex_Mid[PlayerIndex+1].TexNum);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
+ glBegin(GL_QUADS);
+ glTexCoord2f(0, 0); glVertex2f(Rec.Left, Rec.Top);
+ glTexCoord2f(0, 1); glVertex2f(Rec.Left, Rec.Bottom);
+ glTexCoord2f(round((Rec.Right-Rec.Left)/32), 1); glVertex2f(Rec.Right, Rec.Bottom);
+ glTexCoord2f(round((Rec.Right-Rec.Left)/32), 0); glVertex2f(Rec.Right, Rec.Top);
+ glEnd;
+ glColor3f(1, 1, 1);
+
+ // the right part of the note
+ Rec.Left := Rec.Right;
+ Rec.Right := Rec.Right + NotesW;
+
+ glBindTexture(GL_TEXTURE_2D, Tex_Right[PlayerIndex+1].TexNum);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0, 0); glVertex2f(Rec.Left, Rec.Top);
+ glTexCoord2f(0, 1); glVertex2f(Rec.Left, Rec.Bottom);
+ glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom);
+ glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top);
+ glEnd;
+
+ // Perfect note is stored
+ if Perfect and (Ini.EffectSing=1) then
+ begin
+ A := 1 - 2*(LineState.CurrentTime - GetTimeFromBeat(Start+Length));
+ if not (Start+Length-1 = LineState.CurrentBeatD) then
begin
- with Player[NrGracza].Note[N] do
- begin
- // Left part of note
- Rec.Left := X + (Start-Lines[0].Line[Lines[0].Current].Note[0].Start) * TempR + 0.5 + 10*ScreenX;
- Rec.Right := Rec.Left + NotesW;
-
- // Draw it in half size, if not hit
- if Hit then
- begin
- NotesH2 := NotesH
- end
- else
- begin
- NotesH2 := int(NotesH * 0.65);
- end;
-
- Rec.Top := Y - (Tone-Lines[0].Line[Lines[0].Current].BaseNote)*Space/2 - NotesH2;
- Rec.Bottom := Rec.Top + 2 *NotesH2;
-
- // draw the left part
- glColor3f(1, 1, 1);
- glBindTexture(GL_TEXTURE_2D, Tex_Left[NrGracza+1].TexNum);
- glBegin(GL_QUADS);
- glTexCoord2f(0, 0); glVertex2f(Rec.Left, Rec.Top);
- glTexCoord2f(0, 1); glVertex2f(Rec.Left, Rec.Bottom);
- glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom);
- glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top);
- glEnd;
-
- // Middle part of the note
- Rec.Left := Rec.Right;
- Rec.Right := X + (Start+Length-Lines[0].Line[Lines[0].Current].Note[0].Start) * TempR - NotesW - 0.5 + 10*ScreenX;
-
- // (nowe) - dunno
- if (Start+Length-1 = LineState.CurrentBeatD) then
- Rec.Right := Rec.Right - (1-Frac(LineState.MidBeatD)) * TempR;
- // the left note is more right than the right note itself, sounds weird - so we fix that xD
- if Rec.Right <= Rec.Left then Rec.Right := Rec.Left;
-
- // draw the middle part
- glBindTexture(GL_TEXTURE_2D, Tex_Mid[NrGracza+1].TexNum);
- glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
- glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
- glBegin(GL_QUADS);
- glTexCoord2f(0, 0); glVertex2f(Rec.Left, Rec.Top);
- glTexCoord2f(0, 1); glVertex2f(Rec.Left, Rec.Bottom);
- glTexCoord2f(round((Rec.Right-Rec.Left)/32), 1); glVertex2f(Rec.Right, Rec.Bottom);
- glTexCoord2f(round((Rec.Right-Rec.Left)/32), 0); glVertex2f(Rec.Right, Rec.Top);
- glEnd;
- glColor3f(1, 1, 1);
-
- // the right part of the note
- Rec.Left := Rec.Right;
- Rec.Right := Rec.Right + NotesW;
-
- glBindTexture(GL_TEXTURE_2D, Tex_Right[NrGracza+1].TexNum);
- glBegin(GL_QUADS);
- glTexCoord2f(0, 0); glVertex2f(Rec.Left, Rec.Top);
- glTexCoord2f(0, 1); glVertex2f(Rec.Left, Rec.Bottom);
- glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom);
- glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top);
- glEnd;
-
- // Perfect note is stored
- if Perfect and (Ini.EffectSing=1) then
- begin
- A := 1 - 2*(LineState.CurrentTime - GetTimeFromBeat(Start+Length));
- if not (Start+Length-1 = LineState.CurrentBeatD) then
-
- //Star animation counter
- //inc(Starfr);
- //Starfr := Starfr mod 128;
- GoldenRec.SavePerfectNotePos(Rec.Left, Rec.Top);
- end;
- end; // with
- end; // for
- // eigentlich brauchen wir hier einen vergleich, um festzustellen, ob wir mit
- // singen schon weiter wären, als bei Rec.Right, _auch, wenn nicht gesungen wird_
- // English Translation:
- // actually we need a compare here, to determine if the singing process is ahead Rec.Right
- // even if there is no singing
-
-
- // passing on NrGracza... hope this is really something like the player-number, not only
- // some kind of weird index into a colour-table
-
- if (Ini.EffectSing=1) then
- GoldenRec.GoldenNoteTwinkle(Rec.Top,Rec.Bottom,Rec.Right, NrGracza);
+ //Star animation counter
+ //inc(Starfr);
+ //Starfr := Starfr mod 128;
+ GoldenRec.SavePerfectNotePos(Rec.Left, Rec.Top);
+ end;
+ end;
+ end; // with
+ end; // for
+
+ // actually we need a comparison here, to determine if the singing process
+ // is ahead Rec.Right even if there is no singing
+
+ if (Ini.EffectSing = 1) then
+ GoldenRec.GoldenNoteTwinkle(Rec.Top,Rec.Bottom,Rec.Right, PlayerIndex);
end; // if
end;
//draw Note glow
-procedure SingDrawPlayerBGLine(Left, Top, Right: real; NrLines, NrGracza: integer; Space: integer);
+procedure SingDrawPlayerBGLine(Left, Top, Right: real; NrLines, PlayerIndex: integer; Space: integer);
var
Rec: TRecR;
Count: integer;
@@ -472,87 +465,89 @@ var
lTmpA ,
lTmpB : real;
begin
- if (Player[NrGracza].ScoreTotalI >= 0) then begin
- glColor4f(1, 1, 1, sqrt((1+sin( AudioPlayback.Position * 3))/4)/ 2 + 0.5 );
- glEnable(GL_TEXTURE_2D);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
-
- lTmpA := (Right-Left);
- lTmpB := (Lines[NrLines].Line[Lines[NrLines].Current].End_ - Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start);
-
-
- if ( lTmpA > 0 ) AND
- ( lTmpB > 0 ) THEN
- begin
- TempR := lTmpA / lTmpB;
- end
- else
+ if (Player[PlayerIndex].ScoreTotalInt >= 0) then
begin
- TempR := 0;
- end;
-
- with Lines[NrLines].Line[Lines[NrLines].Current] do begin
- for Count := 0 to HighNote do begin
- with Note[Count] do begin
- if NoteType <> ntFreestyle then begin
- // begin: 14, 20
- // easy: 6, 11
- W := NotesW * 2 + 2;
- H := NotesH * 1.5 + 3.5;
-
- X2 := (Start-Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start) * TempR + Left + 0.5 + 10*ScreenX + 4; // wciecie
- X1 := X2-W;
-
- X3 := (Start+Length-Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start) * TempR + Left - 0.5 + 10*ScreenX - 4; // wciecie
- X4 := X3+W;
-
- // left
- Rec.Left := X1;
- Rec.Right := X2;
- Rec.Top := Top - (Tone-BaseNote)*Space/2 - H;
- Rec.Bottom := Rec.Top + 2 * H;
-
- glBindTexture(GL_TEXTURE_2D, Tex_BG_Left[NrGracza+1].TexNum);
- glBegin(GL_QUADS);
- glTexCoord2f(0, 0); glVertex2f(Rec.Left, Rec.Top);
- glTexCoord2f(0, 1); glVertex2f(Rec.Left, Rec.Bottom);
- glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom);
- glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top);
- glEnd;
-
-
- // srodkowa czesc
- Rec.Left := X2;
- Rec.Right := X3;
+ glColor4f(1, 1, 1, sqrt((1+sin( AudioPlayback.Position * 3))/4)/ 2 + 0.5 );
+ glEnable(GL_TEXTURE_2D);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glBindTexture(GL_TEXTURE_2D, Tex_BG_Mid[NrGracza+1].TexNum);
- glBegin(GL_QUADS);
- glTexCoord2f(0, 0); glVertex2f(Rec.Left, Rec.Top);
- glTexCoord2f(0, 1); glVertex2f(Rec.Left, Rec.Bottom);
- glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom);
- glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top);
- glEnd;
+ lTmpA := (Right-Left);
+ lTmpB := (Lines[NrLines].Line[Lines[NrLines].Current].End_ - Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start);
- // prawa czesc
- Rec.Left := X3;
- Rec.Right := X4;
+ if ( lTmpA > 0 ) and
+ ( lTmpB > 0 ) then
+ begin
+ TempR := lTmpA / lTmpB;
+ end
+ else
+ begin
+ TempR := 0;
+ end;
- glBindTexture(GL_TEXTURE_2D, Tex_BG_Right[NrGracza+1].TexNum);
- glBegin(GL_QUADS);
- glTexCoord2f(0, 0); glVertex2f(Rec.Left, Rec.Top);
- glTexCoord2f(0, 1); glVertex2f(Rec.Left, Rec.Bottom);
- glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom);
- glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top);
- glEnd;
- end; // if not FreeStyle
- end; // with
- end; // for
- end; // with 1
+ with Lines[NrLines].Line[Lines[NrLines].Current] do
+ begin
+ for Count := 0 to HighNote do
+ begin
+ with Note[Count] do
+ begin
+ if NoteType <> ntFreestyle then
+ begin
+ // begin: 14, 20
+ // easy: 6, 11
+ W := NotesW * 2 + 2;
+ H := NotesH * 1.5 + 3.5;
+
+ X2 := (Start-Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start) * TempR + Left + 0.5 + 10*ScreenX + 4; // wciecie
+ X1 := X2-W;
+
+ X3 := (Start+Length-Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start) * TempR + Left - 0.5 + 10*ScreenX - 4; // wciecie
+ X4 := X3+W;
+
+ // left
+ Rec.Left := X1;
+ Rec.Right := X2;
+ Rec.Top := Top - (Tone-BaseNote)*Space/2 - H;
+ Rec.Bottom := Rec.Top + 2 * H;
+
+ glBindTexture(GL_TEXTURE_2D, Tex_BG_Left[PlayerIndex+1].TexNum);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0, 0); glVertex2f(Rec.Left, Rec.Top);
+ glTexCoord2f(0, 1); glVertex2f(Rec.Left, Rec.Bottom);
+ glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom);
+ glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top);
+ glEnd;
+
+ // srodkowa czesc
+ Rec.Left := X2;
+ Rec.Right := X3;
+
+ glBindTexture(GL_TEXTURE_2D, Tex_BG_Mid[PlayerIndex+1].TexNum);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0, 0); glVertex2f(Rec.Left, Rec.Top);
+ glTexCoord2f(0, 1); glVertex2f(Rec.Left, Rec.Bottom);
+ glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom);
+ glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top);
+ glEnd;
+
+ // prawa czesc
+ Rec.Left := X3;
+ Rec.Right := X4;
+
+ glBindTexture(GL_TEXTURE_2D, Tex_BG_Right[PlayerIndex+1].TexNum);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0, 0); glVertex2f(Rec.Left, Rec.Top);
+ glTexCoord2f(0, 1); glVertex2f(Rec.Left, Rec.Bottom);
+ glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom);
+ glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top);
+ glEnd;
+ end; // if not FreeStyle
+ end; // with
+ end; // for
+ end; // with
- glDisable(GL_BLEND);
- glDisable(GL_TEXTURE_2D);
+ glDisable(GL_BLEND);
+ glDisable(GL_TEXTURE_2D);
end;
end;
diff --git a/Game/Code/Classes/UFiles.pas b/Game/Code/Classes/UFiles.pas
index 6b506574..af434b94 100644
--- a/Game/Code/Classes/UFiles.pas
+++ b/Game/Code/Classes/UFiles.pas
@@ -47,7 +47,7 @@ begin
Lines[Count].Line[0].Lyric := '';
Lines[Count].Line[0].LyricWidth := 0;
Player[Count].Score := 0;
- Player[Count].IlNut := 0;
+ Player[Count].LengthNote := 0;
Player[Count].HighNote := -1;
end;
diff --git a/Game/Code/Classes/UIni.pas b/Game/Code/Classes/UIni.pas
index 0f31649c..5e651be0 100644
--- a/Game/Code/Classes/UIni.pas
+++ b/Game/Code/Classes/UIni.pas
@@ -15,6 +15,21 @@ uses
SysUtils;
type
+ // TInputDeviceConfig stores the configuration for an input device.
+ // Configurations will be stored in the InputDeviceConfig array.
+ // Note that not all devices listed in InputDeviceConfig are active devices.
+ // Some might be unplugged and hence unavailable.
+ // Available devices are held in TAudioInputProcessor.DeviceList. Each
+ // TAudioInputDevice listed there has a CfgIndex field which is the index to
+ // its configuration in the InputDeviceConfig array.
+ // Name:
+ // the name of the input device
+ // Input:
+ // the index of the input source to use for recording
+ // ChannelToPlayerMap:
+ // mapping of recording channels to players, e.g. ChannelToPlayerMap[0] = 2
+ // maps the channel 0 (left) to player 2. A player index of 0 means that
+ // the channel is not assigned to a player.
PInputDeviceConfig = ^TInputDeviceConfig;
TInputDeviceConfig = record
Name: string;
diff --git a/Game/Code/Classes/UMain.pas b/Game/Code/Classes/UMain.pas
index 3e1a4ea1..f83830bb 100644
--- a/Game/Code/Classes/UMain.pas
+++ b/Game/Code/Classes/UMain.pas
@@ -25,6 +25,17 @@ uses
UThemes;
type
+ PPLayerNote = ^TPlayerNote;
+ TPlayerNote = record
+ Start: integer;
+ Length: integer;
+ Detect: real; // accurate place, detected in the note
+ Tone: real;
+ Perfect: boolean; // true if the note matches the original one, lit the star
+ Hit: boolean; // true if the note Hits the Line
+ end;
+
+ PPLayer = ^TPlayer;
TPlayer = record
Name: string;
@@ -37,10 +48,10 @@ type
ScoreLine: real;
ScoreGolden: real;
- ScoreI: integer;
- ScoreLineI: integer;
- ScoreGoldenI: integer;
- ScoreTotalI: integer;
+ ScoreInt: integer;
+ ScoreLineInt: integer;
+ ScoreGoldenInt: integer;
+ ScoreTotalInt: integer;
// LineBonus Mod
ScoreLast: Real;//Last Line Score
@@ -50,18 +61,9 @@ type
//Meter: real;
- HighNote: integer;
- IlNut: integer;
- Note: array of record
- Start: integer;
- Length: integer;
- Detekt: real; // accurate place, detected in the note
- Tone: real;
- Perfect: boolean; // true if the note matches the original one, lit the star
-
- // Half size Notes Patch
- Hit: boolean; // true if the note Hits the Line
- end;
+ HighNote: integer; // index of last note (= High(Note)?)
+ LengthNote: integer; // number of notes (= Length(Note)?).
+ Note: array of TPlayerNote;
end;
@@ -85,10 +87,10 @@ var
UserCoversPath: string = '';
UserPlaylistPath: string = '';
- OGL: Boolean;
Done: Boolean;
Event: TSDL_event;
- FileName: string;
+ // FIXME: ConversionFileName should not be global
+ ConversionFileName: string;
Restart: boolean;
// player and music info
@@ -97,18 +99,22 @@ var
CurrentSong : TSong;
+const
+ MAX_SONG_SCORE = 10000; // max. achievable points per song
+ MAX_SONG_LINE_BONUS = 1000; // max. achievable line bonus per song
+
procedure InitializePaths;
Procedure Main;
procedure MainLoop;
procedure CheckEvents;
-procedure Sing(Sender: TScreenSing);
-procedure NewSentence(Sender: TScreenSing);
-procedure NewBeat(Sender: TScreenSing); // executed when on then new beat
-procedure NewBeatC(Sender: TScreenSing); // executed when on then new beat for click
-procedure NewBeatD(Sender: TScreenSing); // executed when on then new beat for detection
+procedure Sing(Screen: TScreenSing);
+procedure NewSentence(Screen: TScreenSing);
+procedure NewBeat(Screen: TScreenSing); // executed when on then new beat
+procedure NewBeatClick(Screen: TScreenSing); // executed when on then new beat for click
+procedure NewBeatDetect(Screen: TScreenSing); // executed when on then new beat for detection
//procedure NewHalf; // executed when in the half between beats
-procedure NewNote(Sender: TScreenSing); // detect note
+procedure NewNote(Screen: TScreenSing); // detect note
function GetMidBeat(Time: real): real;
function GetTimeFromBeat(Beat: integer): real;
procedure ClearScores(PlayerNum: integer);
@@ -206,7 +212,7 @@ begin
Ini := TIni.Create;
Ini.Load;
- //Load Languagefile
+ // Load Languagefile
if (Params.Language <> -1) then
Language.ChangeLanguage(ILanguage[Params.Language])
else
@@ -477,30 +483,29 @@ begin
glViewPort(0, 0, ScreenW, ScreenH);
end
- // ScreenShot hack. If Print is pressed-> Make screenshot and Save to Screenshots Path
+ // if print is pressed -> make screenshot and save to screenshot path
else if (Event.key.keysym.sym = SDLK_SYSREQ) or (Event.key.keysym.sym = SDLK_PRINT) then
Display.SaveScreenShot
- // popup hack... if there is a visible popup then let it handle input instead of underlying screen
+ // if there is a visible popup then let it handle input instead of underlying screen
// shoud be done in a way to be sure the topmost popup has preference (maybe error, then check)
else if (ScreenPopupError <> nil) and (ScreenPopupError.Visible) then
done := not ScreenPopupError.ParseInput(Event.key.keysym.sym, WideChar(Event.key.keysym.unicode), True)
else if (ScreenPopupCheck <> nil) and (ScreenPopupCheck.Visible) then
done := not ScreenPopupCheck.ParseInput(Event.key.keysym.sym, WideChar(Event.key.keysym.unicode), True)
- // end of popup hack
else
begin
- // check for Screen want to Exit
+ // check if screen wants to exit
done := not Display.CurrentScreen^.ParseInput(Event.key.keysym.sym, WideChar(Event.key.keysym.unicode), True);
- // If Screen wants to Exit
+ // if screen wants to exit
if done then
begin
- // If Question Option is enabled then Show Exit Popup
+ // if question option is enabled then show exit popup
if (Ini.AskbeforeDel = 1) then
begin
Display.CurrentScreen^.CheckFadeTo(nil,'MSG_QUIT_USDX');
end
- else // When asking for exit is disabled then simply exit
+ else // if ask-for-exit is disabled then simply exit
begin
Display.Fade := 0;
Display.NextScreenWithCheck := nil;
@@ -510,18 +515,16 @@ begin
end;
end;
- {
SDL_JOYAXISMOTION:
begin
// not implemented
end;
- }
SDL_JOYBUTTONDOWN:
begin
// not implemented
end;
- end; // Case
- end; // While
+ end; // case
+ end; // while
end;
function GetTimeForBeats(BPM, Beats: real): real;
@@ -570,17 +573,18 @@ function GetMidBeat(Time: real): real;
var
CurBeat: real;
CurBPM: integer;
-// TopBeat: real;
-// TempBeat: real;
-// TempTime: real;
+ //TopBeat: real;
+ //TempBeat: real;
+ //TempTime: real;
begin
Result := 0;
if Length(CurrentSong.BPM) = 1 then
Result := Time * CurrentSong.BPM[0].BPM / 60;
- (* 2 BPMs *)
-{ if Length(CurrentSong.BPM) > 1 then begin
- (* new system *)
+ // 2 BPMs
+ {
+ if Length(CurrentSong.BPM) > 1 then begin
+ // new system
CurBeat := 0;
TopBeat := GetBeats(CurrentSong.BPM[0].BPM, Time);
if TopBeat > CurrentSong.BPM[1].StartBeat then begin
@@ -593,12 +597,13 @@ begin
end
else
begin
- (* pierwszy przedzial *)
+ // first part
Result := TopBeat;
end;
- end;}
+ end;
+ }
- (* more BPMs *)
+ // more BPMs
if Length(CurrentSong.BPM) > 1 then
begin
CurBeat := 0;
@@ -621,7 +626,7 @@ begin
if Length(CurrentSong.BPM) = 1 then
Result := CurrentSong.GAP / 1000 + Beat * 60 / CurrentSong.BPM[0].BPM;
- (* more BPMs *)
+ // more BPMs
if Length(CurrentSong.BPM) > 1 then
begin
Result := CurrentSong.GAP / 1000;
@@ -657,7 +662,7 @@ begin
end; // if}
end;
-procedure Sing(Sender: TScreenSing);
+procedure Sing(Screen: TScreenSing);
var
Count: integer;
CountGr: integer;
@@ -666,19 +671,22 @@ var
N: integer;
begin
LineState.OldBeat := LineState.CurrentBeat;
- LineState.MidBeat := GetMidBeat(LineState.CurrentTime - (CurrentSong.Gap{ + 90 I've forgotten for what it is}) / 1000); // new system with variable BPM in function
+ // new system with variable BPM in function
+ LineState.MidBeat := GetMidBeat(LineState.CurrentTime -
+ (CurrentSong.Gap {+ 90 I've forgotten for what it is}) / 1000);
LineState.CurrentBeat := Floor(LineState.MidBeat);
-// LineState.OldHalf := LineState.AktHalf;
-// LineState.MidHalf := LineState.MidBeat + 0.5;
-// LineState.AktHalf := Floor(LineState.MidHalf);
+ //LineState.OldHalf := LineState.AktHalf;
+ //LineState.MidHalf := LineState.MidBeat + 0.5;
+ //LineState.AktHalf := Floor(LineState.MidHalf);
LineState.OldBeatC := LineState.CurrentBeatC;
LineState.MidBeatC := GetMidBeat(LineState.CurrentTime - (CurrentSong.Gap) / 1000);
LineState.CurrentBeatC := Floor(LineState.MidBeatC);
LineState.OldBeatD := LineState.CurrentBeatD;
- LineState.MidBeatD := -0.5+GetMidBeat(LineState.CurrentTime - (CurrentSong.Gap + 120 + 20) / 1000); // MidBeat with addition GAP
+ // MidBeat with additional GAP
+ LineState.MidBeatD := -0.5+GetMidBeat(LineState.CurrentTime - (CurrentSong.Gap + 120 + 20) / 1000);
LineState.CurrentBeatD := Floor(LineState.MidBeatD);
LineState.FracBeatD := Frac(LineState.MidBeatD);
@@ -686,40 +694,40 @@ begin
for CountGr := 0 to 0 do //High(Gracz)
begin;
CP := CountGr;
- // ustawianie starej parts
+ // old parts
LineState.OldLine := Lines[CP].Current;
- // wybieranie aktualnej parts
+ // choose current parts
for Count := 0 to Lines[CP].High do
begin
if LineState.CurrentBeat >= Lines[CP].Line[Count].Start then
Lines[CP].Current := Count;
end;
- // czysczenie nut gracza, gdy to jest nowa plansza
- // (optymizacja raz na halfbeat jest zla)
+ // clean player note if there is a new line
+ // (optimization on halfbeat time)
if Lines[CP].Current <> LineState.OldLine then
- NewSentence(Sender);
+ NewSentence(Screen);
end; // for CountGr
- // wykonuje operacje raz na beat
+ // execute operations on beat
if (LineState.CurrentBeat >= 0) and (LineState.OldBeat <> LineState.CurrentBeat) then
- NewBeat(Sender);
+ NewBeat(Screen);
// make some operations on clicks
if {(LineState.CurrentBeatC >= 0) and }(LineState.OldBeatC <> LineState.CurrentBeatC) then
- NewBeatC(Sender);
+ NewBeatClick(Screen);
// make some operations when detecting new voice pitch
if (LineState.CurrentBeatD >= 0) and (LineState.OldBeatD <> LineState.CurrentBeatD) then
- NewBeatD(Sender);
+ NewBeatDetect(Screen);
- // wykonuje operacje w polowie beatu
+ // execute operations on beat field
// if (LineState.AktHalf >= 1) and (LineState.OldHalf <> LineState.AktHalf) then
// NewHalf;
- // plynnie przesuwa text
+ // remove moving text
Done := 1;
for N := 0 to Lines[0].Line[Lines[0].Current].HighNote do
begin
@@ -732,40 +740,41 @@ begin
N := Lines[0].Line[Lines[0].Current].HighNote;
- // wylacza ostatnia nute po przejsciu
+ // if last note is used
{// todo: Lyrics
if (Ini.LyricsEffect = 1) and (Done = 1) and
(LineState.MidBeat > Lines[0].Line[Lines[0].Current].Note[N].Start + Lines[0].Line[Lines[0].Current].Note[N].Length)
- then Sender.LyricMain.Selected := -1;
+ then Screen.LyricMain.Selected := -1;
if Done > 1 then Done := 1;
- Sender.LyricMain.Done := Done; }
+ Screen.LyricMain.Done := Done;
+ }
// use Done with LCD
-{ with ScreenSing do begin
+ {
+ with ScreenSing do begin
if LyricMain.Selected >= 0 then begin
LCD.MoveCursor(1, LyricMain.SelectedLetter + Round((LyricMain.SelectedLength-1) * Done));
LCD.ShowCursor;
end;
- end;}
-
-
+ end;
+ }
end;
-procedure NewSentence(Sender: TScreenSing);
+procedure NewSentence(Screen: TScreenSing);
var
-G: Integer;
+ i: Integer;
begin
- // czyszczenie nut graczy
- for G := 0 to High(Player) do
+ // clean note of player
+ for i := 0 to High(Player) do
begin
- Player[G].IlNut := 0;
- Player[G].HighNote := -1;
- SetLength(Player[G].Note, 0);
+ Player[i].LengthNote := 0;
+ Player[i].HighNote := -1;
+ SetLength(Player[i].Note, 0);
end;
- // Add Words to Lyrics
- with Sender do
+ // add words to lyrics
+ with Screen do
begin
{LyricMain.AddCzesc(Lines[0].Current);
if Lines[0].Current < Lines[0].High then
@@ -776,19 +785,19 @@ begin
Lyrics.AddLine(@Lines[0].Line[Lyrics.LineCounter]);
end;
- //Sender.UpdateLCD;
+ //Screen.UpdateLCD;
- //On Sentence Change...
- Sender.onSentenceChange(Lines[0].Current);
+ // on sentence change...
+ Screen.onSentenceChange(Lines[0].Current);
end;
-procedure NewBeat(Sender: TScreenSing);
+procedure NewBeat(Screen: TScreenSing);
var
Count: integer;
-// TempBeat: integer;
+ //TempBeat: integer;
begin
- // ustawia zaznaczenie tekstu
-// SingScreen.LyricMain.Selected := -1;
+ // add a text mark
+ //SingScreen.LyricMain.Selected := -1;
for Count := 0 to Lines[0].Line[Lines[0].Current].HighNote do
if (Lines[0].Line[Lines[0].Current].Note[Count].Start = LineState.CurrentBeat) then
begin
@@ -796,45 +805,48 @@ begin
//Todo: Lyrics
//Sender.LyricMain.Selected := Count;
-// LCD.MoveCursor(1, ScreenSing.LyricMain.SelectedLetter);
-// LCD.ShowCursor;
+ //LCD.MoveCursor(1, ScreenSing.LyricMain.SelectedLetter);
+ //LCD.ShowCursor;
//LCD.MoveCursorBR(Sender.LyricMain.SelectedLetter);
//LCD.ShowCursor;
end;
end;
-procedure NewBeatC;
+procedure NewBeatClick;
var
Count: integer;
-// LPT_1: integer;
-// LPT_2: integer;
+ //LPT_1: integer;
+ //LPT_2: integer;
begin
-// LPT_1 := 1;
-// LPT_2 := 1;
+ //LPT_1 := 1;
+ //LPT_2 := 1;
// beat click
- if (Ini.BeatClick = 1) and ((LineState.CurrentBeatC + Lines[0].Resolution + Lines[0].NotesGAP) mod Lines[0].Resolution = 0) then
+ if ((Ini.BeatClick = 1) and
+ ((LineState.CurrentBeatC + Lines[0].Resolution + Lines[0].NotesGAP) mod Lines[0].Resolution = 0)) then
+ begin
AudioPlayback.PlaySound(SoundLib.Click);
+ end;
+ {
// debug system on LPT
if ((LineState.CurrentBeatC + Lines[0].Resolution + Lines[0].NotesGAP) mod Lines[0].Resolution = 0) then
begin
- //LPT_1 := 0;
-// Light.LightOne(0, 150);
+ LPT_1 := 0;
+ Light.LightOne(0, 150);
- (*
Light.LightOne(1, 200); // beat light
if ParamStr(1) = '-doublelights' then
Light.LightOne(0, 200); // beat light
- *)
-{ if ((LineState.CurrentBeatC + Lines[0].Resolution + Lines[0].NotesGAP) mod (Lines[0].Resolution * 2) = 0) then
+ if ((LineState.CurrentBeatC + Lines[0].Resolution + Lines[0].NotesGAP) mod (Lines[0].Resolution * 2) = 0) then
Light.LightOne(0, 150)
else
- Light.LightOne(1, 150)}
+ Light.LightOne(1, 150)
end;
+ }
for Count := 0 to Lines[0].Line[Lines[0].Current].HighNote do
begin
@@ -844,113 +856,127 @@ begin
if Ini.ClickAssist = 1 then
AudioPlayback.PlaySound(SoundLib.Click);
+ {
//LPT_2 := 0;
- (*
if ParamStr(1) <> '-doublelights' then
Light.LightOne(0, 150); //125
- *)
+ }
// drum machine
(*
TempBeat := LineState.CurrentBeat;// + 2;
if (TempBeat mod 8 = 0) then Music.PlayDrum;
if (TempBeat mod 8 = 4) then Music.PlayClap;
-// if (TempBeat mod 4 = 2) then Music.PlayHihat;
+ //if (TempBeat mod 4 = 2) then Music.PlayHihat;
if (TempBeat mod 4 <> 0) then Music.PlayHihat;
*)
end;
end;
{$IFDEF UseSerialPort}
- // PortWriteB($378, LPT_1 + LPT_2 * 2); // 0 zapala
+ // PortWriteB($378, LPT_1 + LPT_2 * 2); // 0 light
{$ENDIF}
end;
-procedure NewBeatD(Sender: TScreenSing);
+procedure NewBeatDetect(Screen: TScreenSing);
begin
- NewNote(Sender);
+ NewNote(Screen);
end;
-procedure NewNote(Sender: TScreenSing);
+procedure NewNote(Screen: TScreenSing);
var
- CP: integer; // current player
- S: integer; // sentence
- SMin: integer;
- SMax: integer;
- SDet: integer; // temporary: sentence of detected note
- Count: integer;
- Mozna: boolean;
- New: boolean;
- Range: integer;
- NoteHit:boolean;
- MaxPoints: integer; // maximal points without line bonus
+ LineFragmentIndex: integer;
+ CurrentLineFragment: PLineFragment;
+ PlayerIndex: integer;
+ CurrentSound: TCaptureBuffer;
+ CurrentPlayer: PPlayer;
+ LastPlayerNote: PPLayerNote;
+ Line: PLine;
+ SentenceIndex: integer;
+ SentenceMin: integer;
+ SentenceMax: integer;
+ SentenceDetected: integer; // sentence of detected note
+ NoteAvailable: boolean;
+ NewNote: boolean;
+ Range: integer;
+ NoteHit: boolean;
+ MaxSongPoints: integer; // max. points for the song (without line bonus)
+ MaxLinePoints: Real; // max. points for the current line
begin
- // Log.LogStatus('Beat ' + IntToStr(LineState.CurrentBeat) + ' HalfBeat ' + IntToStr(LineState.AktHalf), 'NewBeat');
-
- // On linux we get an AV @ NEWNOTE, line 600 of Classes/UMain.pas
- if not assigned( AudioInputProcessor.Sound ) then
- exit;
-
- // analizuje dla obu graczy ten sam sygnal (Sound.OneSrcForBoth)
- // albo juz lepiej nie
- for CP := 0 to PlayersPlay-1 do
- begin
- // analyze buffer
- AudioInputProcessor.Sound[CP].AnalyzeBuffer;
+ //Log.LogStatus('Beat ' + IntToStr(LineState.CurrentBeat) + ' HalfBeat ' + IntToStr(LineState.AktHalf), 'NewBeat');
- // adds some noise
- //LineState.Tone := LineState.Tone + Round(Random(3)) - 1;
+ // TODO: add duet mode support
+ // use Lines[LineSetIndex] with LineSetIndex depending on the current player
- // count min and max sentence range for checking (detection is delayed to the notes we see on the screen)
- SMin := Lines[0].Current-1;
- if SMin < 0 then
- SMin := 0;
- SMax := Lines[0].Current;
+ // count min and max sentence range for checking (detection is delayed to the notes we see on the screen)
+ SentenceMin := Lines[0].Current-1;
+ if (SentenceMin < 0) then
+ SentenceMin := 0;
+ SentenceMax := Lines[0].Current;
- // check if we can add new note
- Mozna := false;
- SDet:=SMin;
- for S := SMin to SMax do
+ // check for an active note at the current time defined in the lyrics
+ NoteAvailable := false;
+ SentenceDetected := SentenceMin;
+ for SentenceIndex := SentenceMin to SentenceMax do
+ begin
+ Line := @Lines[0].Line[SentenceIndex];
+ for LineFragmentIndex := 0 to Line.HighNote do
begin
- for Count := 0 to Lines[0].Line[S].HighNote do
+ CurrentLineFragment := @Line.Note[LineFragmentIndex];
+ // check if line is active
+ if ((CurrentLineFragment.Start <= LineState.CurrentBeatD) and
+ (CurrentLineFragment.Start + CurrentLineFragment.Length-1 >= LineState.CurrentBeatD)) and
+ (CurrentLineFragment.NoteType <> ntFreestyle) and // but ignore FreeStyle notes
+ (CurrentLineFragment.Length > 0) then // and make sure the note lengths is at least 1
begin
- if ((Lines[0].Line[S].Note[Count].Start <= LineState.CurrentBeatD)
- and (Lines[0].Line[S].Note[Count].Start + Lines[0].Line[S].Note[Count].Length - 1 >= LineState.CurrentBeatD))
- and (Lines[0].Line[S].Note[Count].NoteType <> ntFreestyle) // but don't allow when it's FreeStyle note
- and (Lines[0].Line[S].Note[Count].Length > 0) then // and make sure the note lengths is at least 1
- begin
- SDet := S;
- Mozna := true;
- Break;
- end;
+ SentenceDetected := SentenceIndex;
+ NoteAvailable := true;
+ Break;
end;
end;
+ // TODO: break here, if NoteAvailable is true? We would then use the first instead
+ // of the last note matching the current beat if notes overlap. But notes
+ // should not overlap at all.
+ //if (NoteAvailable) then
+ // Break;
+ end;
- S := SDet;
+ // analyze player signals
+ for PlayerIndex := 0 to PlayersPlay-1 do
+ begin
+ CurrentPlayer := @Player[PlayerIndex];
+ CurrentSound := AudioInputProcessor.Sound[PlayerIndex];
+ LastPlayerNote := @CurrentPlayer.Note[CurrentPlayer.HighNote];
- //Czas.SzczytJest := true;
- //Czas.Tone := 27;
+ // analyze buffer
+ CurrentSound.AnalyzeBuffer;
+
+ // add some noise
+ // TODO: do we need this?
+ //LineState.Tone := LineState.Tone + Round(Random(3)) - 1;
- // gdy moze, to dodaje nute - When Mozna, it adds note (?)
- if (AudioInputProcessor.Sound[CP].ToneValid) and (Mozna) then
+ // add note if possible
+ if (CurrentSound.ToneValid and NoteAvailable) then
begin
- // operowanie na ostatniej nucie
- for Count := 0 to Lines[0].Line[S].HighNote do
+ Line := @Lines[0].Line[SentenceDetected];
+
+ // process until last note
+ for LineFragmentIndex := 0 to Line.HighNote do
begin
- if (Lines[0].Line[S].Note[Count].Start <= LineState.OldBeatD+1) and
- (Lines[0].Line[S].Note[Count].Start +
- Lines[0].Line[S].Note[Count].Length > LineState.OldBeatD+1) then
+ CurrentLineFragment := @Line.Note[LineFragmentIndex];
+ if (CurrentLineFragment.Start <= LineState.OldBeatD+1) and
+ (CurrentLineFragment.Start + CurrentLineFragment.Length > LineState.OldBeatD+1) then
begin
- // to robi, tylko dla pary nut (oryginalnej i gracza)
+ // compare notes (from song-file and from player)
- // przesuwanie tonu w odpowiednia game
- while (AudioInputProcessor.Sound[CP].Tone - Lines[0].Line[S].Note[Count].Tone > 6) do
- AudioInputProcessor.Sound[CP].Tone := AudioInputProcessor.Sound[CP].Tone - 12;
+ // move players tone to proper octave
+ while (CurrentSound.Tone - CurrentLineFragment.Tone > 6) do
+ CurrentSound.Tone := CurrentSound.Tone - 12;
- while (AudioInputProcessor.Sound[CP].Tone - Lines[0].Line[S].Note[Count].Tone < -6) do
- AudioInputProcessor.Sound[CP].Tone := AudioInputProcessor.Sound[CP].Tone + 12;
+ while (CurrentSound.Tone - CurrentLineFragment.Tone < -6) do
+ CurrentSound.Tone := CurrentSound.Tone + 12;
- // Half size Notes Patch
+ // half size notes patch
NoteHit := false;
//if Ini.Difficulty = 0 then Range := 2;
@@ -958,96 +984,115 @@ begin
//if Ini.Difficulty = 2 then Range := 0;
Range := 2 - Ini.Difficulty;
- if abs(Lines[0].Line[S].Note[Count].Tone - AudioInputProcessor.Sound[CP].Tone) <= Range then
+ // check if the player hit the correct tone within the tolerated range
+ if (Abs(CurrentLineFragment.Tone - CurrentSound.Tone) <= Range) then
begin
- AudioInputProcessor.Sound[CP].Tone := Lines[0].Line[S].Note[Count].Tone;
+ // adjust the players tone to the correct one
+ // TODO: do we need to do this?
+ CurrentSound.Tone := CurrentLineFragment.Tone;
- // Half size Notes Patch
+ // half size notes patch
NoteHit := true;
-
- MaxPoints := 10000;
- if (Ini.LineBonus <> 0) then
- MaxPoints := 9000;
-
- case Lines[0].Line[S].Note[Count].NoteType of
- ntNormal: Player[CP].Score := Player[CP].Score + MaxPoints / Lines[0].ScoreValue;
- ntGolden: Player[CP].ScoreGolden := Player[CP].ScoreGolden + MaxPoints / Lines[0].ScoreValue;
+
+ if (Ini.LineBonus > 0) then
+ MaxSongPoints := MAX_SONG_SCORE - MAX_SONG_LINE_BONUS
+ else
+ MaxSongPoints := MAX_SONG_SCORE;
+
+ // Note: ScoreValue is the sum of all note values of the song
+ MaxLinePoints := MaxSongPoints / Lines[0].ScoreValue;
+
+ // FIXME: is this correct? Why do we add the points for a whole line
+ // if just one note is correct?
+ case CurrentLineFragment.NoteType of
+ ntNormal: CurrentPlayer.Score := CurrentPlayer.Score + MaxLinePoints;
+ ntGolden: CurrentPlayer.ScoreGolden := CurrentPlayer.ScoreGolden + MaxLinePoints;
end;
- Player[CP].ScoreI := Floor(Player[CP].Score / 10) * 10;
- Player[CP].ScoreGoldenI := Floor(Player[CP].ScoreGolden / 10) * 10;
+ CurrentPlayer.ScoreInt := Floor(CurrentPlayer.Score / 10) * 10;
+ CurrentPlayer.ScoreGoldenInt := Floor(CurrentPlayer.ScoreGolden / 10) * 10;
- Player[CP].ScoreTotalI := Player[CP].ScoreI + Player[CP].ScoreGoldenI + Player[CP].ScoreLineI;
+ CurrentPlayer.ScoreTotalInt := CurrentPlayer.ScoreInt +
+ CurrentPlayer.ScoreGoldenInt +
+ CurrentPlayer.ScoreLineInt;
end;
- end; // operowanie
+ end; // operation
end; // for
- // sprawdzanie czy to nowa nuta, czy przedluzenie
- if S = SMax then
+ // check if we have to add a new note or extend the note's length
+ if (SentenceDetected = SentenceMax) then
begin
- New := true;
+ // we will add a new note
+ NewNote := true;
// if last has the same tone
- if (Player[CP].IlNut > 0 ) and
- (Player[CP].Note[Player[CP].HighNote].Tone = AudioInputProcessor.Sound[CP].Tone) and
- (Player[CP].Note[Player[CP].HighNote].Start + Player[CP].Note[Player[CP].HighNote].Length = LineState.CurrentBeatD) then
+ if ((CurrentPlayer.LengthNote > 0) and
+ (LastPlayerNote.Tone = CurrentSound.Tone) and
+ ((LastPlayerNote.Start + LastPlayerNote.Length) = LineState.CurrentBeatD)) then
begin
- New := false;
+ NewNote := false;
end;
- // if is not as new note to control "beacie" (TODO: translate polish "beacie")
- for Count := 0 to Lines[0].Line[S].HighNote do
+ // if is not as new note to control
+ for LineFragmentIndex := 0 to Line.HighNote do
begin
- if (Lines[0].Line[S].Note[Count].Start = LineState.CurrentBeatD) then
- New := true;
+ if (Line.Note[LineFragmentIndex].Start = LineState.CurrentBeatD) then
+ NewNote := true;
end;
- // dodawanie nowej nuty
- if New then
+ // add new note
+ if NewNote then
begin
- // New Note
- Player[CP].IlNut := Player[CP].IlNut + 1;
- Player[CP].HighNote := Player[CP].HighNote + 1;
- SetLength(Player[CP].Note, Player[CP].IlNut);
- Player[CP].Note[Player[CP].HighNote].Start := LineState.CurrentBeatD;
- Player[CP].Note[Player[CP].HighNote].Length := 1;
- Player[CP].Note[Player[CP].HighNote].Tone := AudioInputProcessor.Sound[CP].Tone; // Ton || TonDokl
- Player[CP].Note[Player[CP].HighNote].Detekt := LineState.MidBeat;
-
- // Half Note Patch
- Player[CP].Note[Player[CP].HighNote].Hit := NoteHit;
-
- //Log.LogStatus('New Note ' + IntToStr(Gracz.Note[Gracz.HighNote].Start), 'NewBeat');
+ // new note
+ Inc(CurrentPlayer.LengthNote);
+ Inc(CurrentPlayer.HighNote);
+ SetLength(CurrentPlayer.Note, CurrentPlayer.LengthNote);
+
+ // update player's last note
+ LastPlayerNote := @CurrentPlayer.Note[CurrentPlayer.HighNote];
+ with LastPlayerNote^ do
+ begin
+ Start := LineState.CurrentBeatD;
+ Length := 1;
+ Tone := CurrentSound.Tone; // Tone || ToneAbs
+ Detect := LineState.MidBeat;
+ Hit := NoteHit; // half note patch
+ end;
end
else
begin
- // przedluzenie nuty
- Player[CP].Note[Player[CP].HighNote].Length := Player[CP].Note[Player[CP].HighNote].Length + 1;
+ // extend note length
+ Inc(LastPlayerNote.Length);
end;
// check for perfect note and then lit the star (on Draw)
- for Count := 0 to Lines[0].Line[S].HighNote do
+ for LineFragmentIndex := 0 to Line.HighNote do
begin
- if (Lines[0].Line[S].Note[Count].Start = Player[CP].Note[Player[CP].HighNote].Start) and
- (Lines[0].Line[S].Note[Count].Length = Player[CP].Note[Player[CP].HighNote].Length) and
- (Lines[0].Line[S].Note[Count].Tone = Player[CP].Note[Player[CP].HighNote].Tone) then
+ CurrentLineFragment := @Line.Note[LineFragmentIndex];
+ if (CurrentLineFragment.Start = LastPlayerNote.Start) and
+ (CurrentLineFragment.Length = LastPlayerNote.Length) and
+ (CurrentLineFragment.Tone = LastPlayerNote.Tone) then
begin
- Player[CP].Note[Player[CP].HighNote].Perfect := true;
+ LastPlayerNote.Perfect := true;
end;
end;
- end; // if S = SMax
+ end; // if SentenceDetected = SentenceMax
+
+ end; // if Detected
+ end; // for PlayerIndex
- end; // if moze
- end; // for CP
- // Log.LogStatus('EndBeat', 'NewBeat');
+ //Log.LogStatus('EndBeat', 'NewBeat');
- //On Sentence End -> For LineBonus + SingBar
- if (sDet >= low(Lines[0].Line)) and (sDet <= high(Lines[0].Line)) then
+ // on sentence end -> for LineBonus and display of SingBar (rating pop-up)
+ if (SentenceDetected >= Low(Lines[0].Line)) and
+ (SentenceDetected <= High(Lines[0].Line)) then
begin
- if assigned( Sender ) and
- ((Lines[0].Line[SDet].Note[Lines[0].Line[SDet].HighNote].Start + Lines[0].Line[SDet].Note[Lines[0].Line[SDet].HighNote].Length - 1) = LineState.CurrentBeatD) then
+ Line := @Lines[0].Line[SentenceDetected];
+ CurrentLineFragment := @Line.Note[Line.HighNote];
+ if ((CurrentLineFragment.Start + CurrentLineFragment.Length - 1) = LineState.CurrentBeatD) then
begin
- Sender.onSentenceEnd(sDet);
+ if assigned(Screen) then
+ Screen.OnSentenceEnd(SentenceDetected);
end;
end;
@@ -1055,22 +1100,25 @@ end;
procedure ClearScores(PlayerNum: integer);
begin
- Player[PlayerNum].Score := 0;
- Player[PlayerNum].ScoreI := 0;
- Player[PlayerNum].ScoreLine := 0;
- Player[PlayerNum].ScoreLineI := 0;
- Player[PlayerNum].ScoreGolden := 0;
- Player[PlayerNum].ScoreGoldenI := 0;
- Player[PlayerNum].ScoreTotalI := 0;
+ with Player[PlayerNum] do
+ begin
+ Score := 0;
+ ScoreInt := 0;
+ ScoreLine := 0;
+ ScoreLineInt := 0;
+ ScoreGolden := 0;
+ ScoreGoldenInt := 0;
+ ScoreTotalInt := 0;
+ end;
end;
//--------------------
-// Function sets all Absolute Paths e.g. Song Path and makes sure the Directorys exist
+// Function sets all absolute paths e.g. song path and makes sure the directorys exist
//--------------------
procedure InitializePaths;
- // Initialize a Path Variable
- // After Setting Paths, make sure that Paths exist
+ // Initialize a path variable
+ // After setting paths, make sure that paths exist
function initialize_path( out aPathVar : string; const aLocation : string ): boolean;
var
lWriteable: Boolean;
diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas
index bad0aa86..35c67ae1 100644
--- a/Game/Code/Classes/UMusic.pas
+++ b/Game/Code/Classes/UMusic.pas
@@ -15,6 +15,25 @@ uses
type
TNoteType = (ntFreestyle, ntNormal, ntGolden);
+ (**
+ * TLineFragment represents a fragment of a lyrics line.
+ * This is a text-fragment (e.g. a syllable) assigned to a note pitch,
+ * represented by a bar in the sing-screen.
+ *)
+ PLineFragment = ^TLineFragment;
+ TLineFragment = record
+ Color: integer;
+ Start: integer; // beat the fragment starts at
+ Length: integer; // length in beats
+ Tone: integer; // full range tone
+ Text: string; // text assigned to this fragment (a syllable, word, etc.)
+ NoteType: TNoteType; // note-type: golden-note/freestyle etc.
+ end;
+
+ (**
+ * TLine represents one lyrics line and consists of multiple
+ * notes.
+ *)
PLine = ^TLine;
TLine = record
Start: integer;
@@ -22,31 +41,31 @@ type
LyricWidth: real;
End_: integer;
BaseNote: integer;
- HighNote: integer;
- TotalNotes: integer;
+ HighNote: integer; // index of last note in line (= High(Note)?)
+ TotalNotes: integer; // value of all notes in the line
LastLine: boolean;
- Note: array of record
- Color: integer;
- Start: integer;
- Length: integer;
- Tone: integer; // full range tone
- Text: string;
- NoteType: TNoteType;
- end;
+ Note: array of TLineFragment;
end;
- ALine = array of TLine; // (TODO: rename to TLineArray)
+ (**
+ * TLines stores sets of lyric lines and information on them.
+ * Normally just one set is defined but in duet mode it might for example
+ * contain two sets.
+ *)
TLines = record
- Current: integer; // for drawing of current line
- High: integer;
+ Current: integer; // for drawing of current line
+ High: integer; // (= High(Line)?)
Number: integer;
Resolution: integer;
NotesGAP: integer;
ScoreValue: integer;
- Line: ALine;
+ Line: array of TLine;
end;
- TLineState = class // all that concerns the current frames
+ (**
+ * TLineState contains all information that concerns the current frames
+ *)
+ TLineState = class
private
Timer: TRelativeTimer; // keeps track of the current time
public
@@ -56,12 +75,14 @@ type
// now we use this for super synchronization!
// only used when analyzing voice
+ // TODO: change ...D to ...Detect(ed)
OldBeatD: integer; // previous discovered beat
CurrentBeatD: integer;
MidBeatD: real; // like CurrentBeatD
FracBeatD: real; // fractional part of MidBeatD
// we use this for audible clicks
+ // TODO: Change ...C to ...Click
OldBeatC: integer; // previous discovered beat
CurrentBeatC: integer;
MidBeatC: real; // like CurrentBeatC
diff --git a/Game/Code/Classes/UParty.pas b/Game/Code/Classes/UParty.pas
index 9fdcf7a6..5b9d2400 100644
--- a/Game/Code/Classes/UParty.pas
+++ b/Game/Code/Classes/UParty.pas
@@ -450,12 +450,12 @@ begin
begin
// to-do : recode Percentage stuff
//PlayerInfo.Playerinfo[I].Percentage := PlayerInfo.Playerinfo[I].Score div 9999;
- if (Player[I].ScoreTotalI > MaxScore) then
+ if (Player[I].ScoreTotalInt > MaxScore) then
begin
- MaxScore := Player[I].ScoreTotalI;
+ MaxScore := Player[I].ScoreTotalInt;
Rounds[CurRound].Winner := 1 shl I;
end
- else if (Player[I].ScoreTotalI = MaxScore) AND (Player[I].ScoreTotalI <> 0) then
+ else if (Player[I].ScoreTotalInt = MaxScore) AND (Player[I].ScoreTotalInt <> 0) then
begin
Rounds[CurRound].Winner := Rounds[CurRound].Winner or (1 shl I);
end;
diff --git a/Game/Code/Classes/USingScores.pas b/Game/Code/Classes/USingScores.pas
index dd326356..645f0f6e 100644
--- a/Game/Code/Classes/USingScores.pas
+++ b/Game/Code/Classes/USingScores.pas
@@ -22,7 +22,7 @@ uses UThemes,
// but not testet yet //
//////////////////////////////////////////////////////////////
-//Some Constances containing Options that could change by time
+//Some constants containing options that could change by time
const
MaxPlayers = 6; //Maximum of Players that could be added
MaxPositions = 6; //Maximum of Score Positions that could be added
@@ -853,14 +853,16 @@ var
Diff: Real;
begin
//Only Draw if Player has a Position
- If Players[Index].Position <> high(byte) then
+ if Players[Index].Position <> high(byte) then
begin
//Only Draw if Player is on Cur Screen
- If ((Players[Index].Position AND 128) = 0) = (ScreenAct = 1) AND (Players[index].RBVisible AND Players[index].Visible) then
+ if (((Players[Index].Position and 128) = 0) = (ScreenAct = 1) and
+ Players[index].RBVisible and
+ Players[index].Visible) then
begin
Position := @Positions[Players[Index].Position and 127];
- If (Enabled AND Players[Index].Enabled) then
+ if (Enabled AND Players[Index].Enabled) then
begin
//Move Position if Enabled
Diff := Players[Index].RBTarget - Players[Index].RBPos;
@@ -871,25 +873,25 @@ begin
end;
//Get Colors for RatingBar
- If Players[index].RBPos <=0.22 then
+ if (Players[index].RBPos <= 0.22) then
begin
R := 1;
G := 0;
B := 0;
end
- Else If Players[index].RBPos <=0.42 then
+ else if (Players[index].RBPos <= 0.42) then
begin
R := 1;
G := Players[index].RBPos*5;
B := 0;
end
- Else If Players[index].RBPos <=0.57 then
+ else if (Players[index].RBPos <= 0.57) then
begin
R := 1;
G := 1;
B := 0;
end
- Else If Players[index].RBPos <=0.77 then
+ else if (Players[index].RBPos <= 0.77) then
begin
R := 1-(Players[index].RBPos-0.57)*5;
G := 1;