Merge branch 'master' of github.com:stepmania/stepmania

This commit is contained in:
freem
2014-09-30 23:36:38 -05:00
3 changed files with 188 additions and 15 deletions
@@ -0,0 +1,183 @@
-- This example describes everything you need to do in your theme to allow the
-- player to enter their heart rate for calorie calculation.
-- First, the metrics you'll need to add to metrics.ini.
-- [ScreenHeartEntry]
-- # The HeartEntryEnabled metric must be set to true so the branching logic
-- # will know that your theme supports the screen.
-- HeartEntryEnabled=true
-- # ScreenHeartEntry uses ScreenWithMenuElements as its fallback, so the
-- # metrics in the ScreenWithMenuElements section will also apply to it.
-- Now for the body of the screen. The things discussed here will have to go
-- in BGAnimations/ScreenHeartEntry overlay.lua
-- The positions the numpads for entering the heart rate will be placed at.
local heart_xs= {
[PLAYER_1]= SCREEN_CENTER_X * 0.625,
[PLAYER_2]= SCREEN_CENTER_X * 1.375,
}
-- heart_entries is a table that will be used to store the numpads that the
-- players will use.
local heart_entries= {}
-- Note that a numpad is only created for a player if that player is enabled
-- and they have the flag set in their profile to enable heart rate entry.
for i, pn in ipairs(GAMESTATE:GetEnabledPlayers()) do
local profile= PROFILEMAN:GetProfile(pn)
if profile and profile:GetIgnoreStepCountCalories() then
-- This is probably the part you'll want to configure the most, the
-- numpads. _fallback/Scripts/04 NumPadEntry.lua discusses configuring a
-- numpad in detail.
heart_entries[pn]= new_numpad_entry{
Name= pn .. "_heart_entry",
InitCommand= cmd(xy, heart_xs[pn], SCREEN_CENTER_Y+48),
-- Settings for value are optional, but you will probably want to
-- change them, so they are provided in this example.
-- If a simple colored BitmapText isn't what you want for displaying
-- the value being entered, read _fallback/Scripts/04 NumPadEntry.lua.
value_pos= {0, -48},
value_font= "Common Normal",
value_color= PlayerColor(pn),
-- Optional prompt settings.
prompt_pos= {0, -72},
prompt_font= "Common Normal",
prompt_color= Color.White,
prompt_text= THEME:GetString("ScreenHeartEntry", "Heart Rate"),
-- Optional button settings.
button_positions= {
{-30, -24}, {0, -24}, {30, -24},
{-30, 0}, {0, 0}, {30, 0},
{-30, 24}, {0, 24}, {30, 24},
{-30, 48}, {0, 48}, {30, 48}
},
button_font= "Common Normal",
button_color= Color.White,
-- Cursor settings. You probably want something more than a quad for
-- the cursor, so this example includes the command the cursor needs
-- to support to do its job.
cursor= Def.Quad{
InitCommand= function(self)
self:SetWidth(16)
self:SetHeight(28)
self:diffuse(PlayerDarkColor(pn))
end,
-- MoveCommand is used to move the cursor to a button.
MoveCommand= function(self, param)
-- param contains the position to move to.
self:stoptweening()
self:decelerate(0.15)
self:xy(param[1], param[2])
end,
-- FitCommand is used to change the size of the cursor to fit the
-- button after it has been moved.
FitCommand= function(self, param)
-- param is the actor for the button.
-- Note that this does not use stoptweening or finishtweening.
-- This is because it is executed with playcommand immediately
-- after MoveCommand, and thus the state changes it makes combine
-- with the actor state at the end of MoveCommand.
self:SetWidth(param:GetWidth())
end
},
-- cursor_draw controls whether the cursor is above or below the
-- buttons.
cursor_draw= "first", -- stick it under the buttons.
-- Don't let the player enter a silly value.
max_value= 300,
-- Automatically move the cursor to the done button when the player has
-- entered three digits.
auto_done_value= 100,
}
end
end
-- This function is the input callback. It handles button presses from the
-- player, passing them to the numpad so the player can enter their heart
-- rate, and detecting when the player is done.
-- See the AddInputCallback function for the Screen class in Lua.xml for a
-- full description of the event argument.
local function input(event)
local pn= event.PlayerNumber
-- If the PlayerNumber isn't set, the button isn't mapped. Ignore it.
if not pn then return end
-- If it's a release, ignore it.
if event.type == "InputEventType_Release" then return end
-- If the player doesn't have a heart_entry, ignore it.
if not heart_entries[pn] then return end
-- Pass the input to the heart_entry for the player. It will handle moving
-- the cursor. If it returns true, the player is done.
local done= heart_entries[pn]:handle_input(event.GameButton)
if done then
-- Play a sound for the player so they know the value was entered.
SOUND:PlayOnce(THEME:GetPathS("Common", "Start"))
-- Check whether all players that need to enter their heart rate are done.
local all_done= true
for pn, entry in pairs(heart_entries) do
if not entry.done then all_done= false break end
end
if all_done then
-- If the players are done, add the calories to their profiles.
for pn, entry in pairs(heart_entries) do
local profile= PROFILEMAN:GetProfile(pn)
if profile and profile:GetIgnoreStepCountCalories() then
-- calories is the value you might want to store off in a global
-- variable to display on evaluation.
local calories= profile:CalculateCaloriesFromHeartRate(
entry.value, GAMESTATE:GetLastGameplayDuration())
profile:AddCaloriesToDailyTotal(calories)
end
end
-- Since all players are done, transition to the next screen.
SCREENMAN:GetTopScreen():StartTransitioningScreen("SM_GoToNextScreen")
end
end
end
-- A simple timer that the player can watch while counting their pulse.
-- The menu timer isn't used because it has undesired side effects.
-- timer_text will be set to the BitmapText used to display the time. This
-- way, the BitmapText doesn't have to be fetched with GetChild every frame.
local timer_text
-- This is an update function for an ActorFrame. It will run every frame.
local function timer_update(self)
local time= math.floor((self:GetSecsIntoEffect() % 60) * 10) / 10
if time < 10 then
timer_text:settext(("0%.1f"):format(time))
else
timer_text:settext(("%.1f"):format(time))
end
end
-- args contains the actors that will be in the ActorFrame for this screen.
local args= {
Def.ActorFrame{
Name= "timer",
InitCommand= function(self)
-- Set the effectperiod so the timer can show an elapsed time.
self:effectperiod(2^16)
-- Set timer_text so GetChild doesn't need to be called every frame.
timer_text= self:GetChild("timer_text")
-- Set the update function so the timer will be updated.
self:SetUpdateFunction(timer_update)
end,
OnCommand= function(self)
-- Add the input callback so input will be handled.
SCREENMAN:GetTopScreen():AddInputCallback(input)
end,
-- The BitmapText used to display the elapsed time.
Def.BitmapText{
Name= "timer_text", Font= "Common Normal", Text= "00.0",
InitCommand= cmd(xy, SCREEN_CENTER_X, SCREEN_CENTER_Y-80; diffuse, Color.White),
OnCommand= cmd(strokecolor,Color.Outline),
}
},
}
-- The actors for the heart_entries are added in a loop so that only the ones
-- that will be used will exist.
for pn, entry in pairs(heart_entries) do
args[#args+1]= entry:create_actors()
end
return Def.ActorFrame(args)
+3 -15
View File
@@ -6,6 +6,7 @@ The first system simply uses the weight of the player and adds a small amount fo
The second system uses age, gender, weight, heart rate, and song duration to calculate the amount used during a song. This requires a theme to support it, and the relevant parts of Editable.ini to be set for the profile.
Editable.ini fields:
The default theme provides a profile editing screen for setting these fields in Stepmania without needing to edit Editable.ini by hand.
BirthYear, -- defaults to 1995
IgnoreStepCountCalories, -- Must be set to 1 to use the second system.
IsMale, -- Defaults to 1. Set to 0 for females.
@@ -29,22 +30,9 @@ CalculateCaloriesFromHeartRate()
Intended usage:
A theme that supports heart rate calorie calculation should take the following steps:
1. Create a new screen that the player will be able to use to enter their heart rate. It shall be called "ScreenHeartEntry" in this list, though a theme can name it anything.
2. During ScreenGameplay, track the amount of time that the player is hitting steps for. This duration must be in seconds.
3. When proceeding from ScreenGameplay:
3a. Check whether GetIgnoreStepCountCalories returns true for either player's profile.
3b. If it returns true for either player, go to ScreenHeartEntry instead of ScreenEvaluationNormal.
3c. This means changing the NextScreen metric for ScreenGameplay to use a function that checks the profiles and returns the correct screen.
4. On ScreenHeartEntry:
4a. Provide a timer that the players can watch while measuring their pulse.
4b. Provide a way for the players to enter their heart rate in beats per minute.
4c. When a player enters their heart rate, use Profile:CalculateCaloriesFromHeartRate().
4d. Do not add calories to a profile if Profile:IgnoreStepCountCalories() returns false for that profile.
4e. Pass the heart rate and the duration from ScreenGameplay to Profile:CalculateCaloriesFromHeartRate() and store its return value.
4f. Pass the return value of Profile:CalculateCaloriesFromHeartRate() to Profile:AddCaloriesToDailyTotal() to add them to the total for that player's profile.
4g. When all active players have finished entering their heart rate, proceed to ScreenEvaluationNormal.
5. This concludes the special steps required for theme support of heart rate calorie calculation.
1. Create ScreenHeartEntry as described in Themerdocs/Examples/Example_Screens/ScreenHeartEntry.lua. _fallback's branching logic will take care of checking whether the screen should be used.
Side notes:
CalculateCaloriesFromHeartRate and AddCaloriesToDailyTotal are separate functions so that a theme can display or use the calorie amount in other ways easily.
If IgnoreStepCountCalories is true for a profile, but the theme in use does not provide support using the steps listed above, that profile will not accumulate calories.
Note that calories will not accumulate during gameplay for a profile that has IgnoreStepCountCalories set to true. PlayerStageStats:GetCaloriesBurned() will also return 0 for that player. You'll have to store the value returned by CalculateCaloriesFromHeartRate in a global variable if you want to display it later on ScreenEvaluation.
@@ -183,6 +183,8 @@
-- -- is a table of x, y, and optional z. Unused if you pass in a custom
-- -- value actor.
-- value_pos= {0, -48},
-- -- Optional. The font to use for the default value actor.
-- value_font= "Common Normal",
-- -- Optional. The color for the default value text. Unused if you pass
-- -- in a custom value actor. Default is White.
-- value_color= Color.White,