En este segundo post intentare explicar como usar los parametros del primer post.
Pero "complicandolo" un poco mas.
Seria "Nivel Medio"
fe.add_image Magic TokensAntes explique como añadir una imagen
Siempre que usemos "fe.add" necesitamos darle un "objeto" por asi llamarle que en este caso es "bg.png" y su posicion.
Siemrpe se usan los dos primeros para posicionarlo en "x" (desde cero hasta la derecha) "y" (desde arriba hasta abajo)
Luego vendria "el tamaño" , si en este caso le ponemos:
Y si queremos que este "objeto" no sea "fijo" sino que cambie , por ejemplo que sea el logo de MAME , Super Nintendo...
Usaremos "Magic Tokens"
The following magic tokens are currently supported:
[DisplayName] - the name of the current display
[ListSize] - the number of items in the game list
[ListEntry] - the number of the current selection in the game list
[FilterName] - the name of the filter
[Search] - the search rule currently applied to the game list
[SortName] - the attribute that the list was sorted by
[Name] - the short name of the selected game
[Title] - the full name of the selected game
[Emulator] - the emulator to use for the selected game
[CloneOf] - the short name of the game that the selection is a clone of
[Year] - the year for the selected game
[Manufacturer] - the manufacturer for the selected game
[Category] - the category for the selected game
[Players] - the number of players for the selected game
[Rotation] - the rotation for the selected game
[Control] - the primary control for the selected game
[Status] - the emulation status for the selected game
[DisplayCount] - the number of displays for the selected game
[DisplayType] - the display type for the selected game
[AltRomname] - the alternative Romname for the selected game
[AltTitle] - the alternative title for the selected game
[PlayedTime] - the amount of time the selected game has been played
[PlayedCount] - the number of times the selected game has been played
[SortValue] - the value used to order the selected game in the list
[System] - the first "System" name configured for the selected game's emulator
[SystemN] - the last "System" name configured for the selected game's emulator
[Overview] - the overview description for the selected game
https://github.com/mickelson/attract/blob/master/Layouts.md#magicUn compañero queria añadir un logo de MAME al layout Basic.
http://arcadespain.info/Foro/index.php?topic=6171.msg80655;topicseen#newLo primero seria buscar el codigo de ese texto para no "poner por encima" el logo:
local l = fe.add_text( "[DisplayName]", 0, 15, 640, 30 );
l.set_rgb( 200, 200, 70 );
l.style = Style.Bold;
Como le ponemos logos en vez de "textos" pues cambiamos por lo siguiente:
local s = fe.add_image( "system/[DisplayName]", 250, 15, 100, 30 );
IMPORTANTE: Esto solo funcionara si creamos una carpeta "system" dentro de la carpeta del layout:
Y dentro obviamente metemos los logos
Este seria el codigo que necesitamos.
local s = fe.add_image( "system/[DisplayName]", 250, 15, 100, 30 );
local l = fe.add_text( "", 0, 15, 640, 30 );
l.set_rgb( 200, 200, 70 );
l.style = Style.Bold;
Mas adelante haremos un layout desde cero si el tema interesa pero para no complicarnos ahora fijaros que dejo esta parte asi:
local l = fe.add_text( "", 0, 15, 640, 30 );
En lugar de eliminarlo completamente xq nos daria mas dolores de cabeza que beneficios.
Esto lo hago xq el layout "llama" al "objeto" l en una funcion y en otras partes asi que mejor dejarlo "vacio" que eliminarlo.
Bueno , lo que nos interesa , asi quedaria el tema:
Igual que antes se puede "modifcar" el tamaño y la posicion variando estos parametros:
local s = fe.add_image( "system/[DisplayName]", 250, 15, 100, 30 );
Si modifcamos 250 por 300 se ira mas a la derecha y viceversa
Si modifcamos 15 por 50 se ira mas a la abajo y viceversa
Si modifcamos 100 por 200 sera mas ancho y viceversa
Si modifcamos 30 por 50 sera mas alto y viceversaIMPORTANTE
Tengo un sistema y le pongo el logo pero no me sale el png...
Posibles motivos , al usar "Magic Tokens" , en este caso DisplayName tenemos que fijarnos en el nombre que tiene nuestro "Display"
Esto en Attract Mode es un poco lio si empezamos de cero , xq DisplayName no es una carpeta ni un archivo , lo encontrariamos en el attract.cfg
display MAME
layout Basic
romlist MAME
in_cycle yes
in_menu yes
filter All
filter Favourites
rule Favourite equals 1
Comento esto porque puede darse el caso de que nos convenga usar otro magic token para nuestro caso concreto , podria ser:
local s = fe.add_image( "system/[Emulator]", 250, 15, 100, 30 );
Si hacemos esto el "nombre" que nos usaria seria los que tenemos en la carpeta Emulators , en este caso podria ser el MAME.cfg
Y si tenemos varios emuladores para un mismo sistema , pues usamos "System"
local s = fe.add_image( "system/[System]", 250, 15, 100, 30 );
Esto de donde lo saca Attract Mode , pues si abrimos cualquier emulator.cfg veremos esta parte:
system Arcade
Para repasar y finalizar esta parte de Magic Tokens con fe.add_image al igual que cambiamos el parametro del magic token tambien se puede cambiar su ubicacion.
Para aclarar "system/[DisplayName]" significa que el layout.nut buscara un archivo con el nombre de nuestro display en una carpeta llamada system situada junto a el.
Si hacemos una carpeta llamada logos pues lo cambiamos por "logos/[DisplayName]"
Y si lo metemos en una subcarpeta "images/logos" pues igual
local s = fe.add_image( "images/logos/[DisplayName]", 250, 15, 100, 30 );
Asi quedaria el tema cambiando el texto por un logo con su bg.png original sin el verdoso que le puse antes
fe.add_artwork fe.load_moduleEn nuestro ejemplo tenemos un artwork "flyer" debajo de la lista de roms.
Para que luzca un poco mas le añadiremos una animacion para que pase de ser invisible a verse mediante una pequeña transicion.
Para ello nos serviremos de los "modulos" que nos ayudan a crear esa transicion sin tener que escribir el codigo completo necesario para que se produzca.
// modules
fe.load_module("fade");
fe.load_module( "animate" );
Se suelen colocar al principio del layout.nut y deben estar en la carpeta modules de nuestra instalacion.
Se necesitarian dos transicions , una para cuando arrancamos attract mode o cambiamos de layout y otra para cuando nos movemos por la lista de roms.
local v = fe.add_artwork( "flyer", 32, 64, 262, 352 );
v.alpha = 0;
local v_alpha_onload = {
when = When.StartLayout,
when = Transition.ToNewList,
property = "alpha",
start = 0,
end = 155,
time = 1500,
tween = Tween.Expo
}
animation.add( PropertyAnimation ( v, v_alpha_onload ) );
Esta seria la primera , y aqui desglosado:
v.alpha = 0
Esto hace que nuestro flyer sea "invisible" luego con la transicion haremos que aparezca.
Esta seria la parte donde le damos las "caracteristicas" de nuestra transicion:
local v_alpha_onload = {
Cuando queremos que se ejcute , en este caso cuando iniciemos el layout "When.StartLayout" y cuando cambiemos de lista "Transition.ToNewList" , esto se hace para cuando nos movemos entre filtros para que el flyer no quede invisible si por ejemplo pasas de la lista "plataformas" a la lista "shooter".
when = When.StartLayout,
when = Transition.ToNewList,
Esto le indica que empiece en 0 y termine en 155 (alpha 255 seria lo maximo posible)
start = 0,
end = 155,
El tiempo que queremos que dure la transicion:
time = 1500,
El "tipo" de transicion , para esto se usa el modulo "animate"
tween = Tween.Expo
Por ultimo se necesita "ejecutarla"
animation.add( PropertyAnimation ( v, v_alpha_onload ) );
"v" es el nombre que le dimos a nuestro "objeto" flyer.
"v_alpha_onload" el nombre de nuestra transicion.
Si abrimos el modulo "animate.nut" nos explica como usarlo.
ANIMATION CONFIGS:
Configs are flexible and options vary depending on the Animation class you are using. The base options are:
//handled by Animation base class
when = When.ToNewSelection // when the animation starts (can use Transition, but other When options are available)
time = 500 // length of animation in ms
delay = 0 // delay before animation starts in ms
wait = false // whether this is a waiting animation during transitions (complete before continuing)
loop = false // whether to loop the animation (can also be a number)
pulse = false // whether to pulse the animation (can also be a number), use onReverse() to handle reversing your animation - by default, it will reverse start/end values
tween = Tween.Linear // type of tween to use during animation (use calculate to determine tween/easing value)
easing = Easing.Out // type of easing to use during animation (use calculate to determine tween/easing value)
Ademas en el zip de github del propio attract mode en "attract-master\config\layouts\Sample Animate" encontraremos mucha informacion por si alguien quiere profundizar en el tema.
Lo siguiente seria la transicion para cuando nos movemos entre roms:
local v_alpha = {
when = Transition.ToNewSelection,
property = "alpha",
start = 0,
end = 155,
time = 1500,
tween = Tween.Expo
}
animation.add( PropertyAnimation ( v, v_alpha ) );
Seria exactamente igual que la otra salvo en dos cosas , su nombre tiene que ser diferente a la otra "v_alpha" y la ejecutamos solo cuando nos movemos en la lista de roms "Transition.ToNewSelection"
Este seria el resultado:
fe.add_sound function fe.game_infoEste codigo no es mio y aun no lo he probado , es de Calle81 del grupo de Hyperpie.
http://forum.attractmode.org/index.php?topic=1793.0////////////////
//Background Music
////////////
local bgMusic = fe.add_sound("")
function bgmusic_transitions( ttype, var, ttime ) {
switch ( ttype ) {
case Transition.FromOldSelection:
bgMusic.playing=false
bgMusic.file_name = "../../music/"+fe.game_info(Info.Title)+".mp3"
bgMusic.playing=true
bgMusic.loop=true
break;
case Transition.ToGame:
case Transition.ToNewList:
bgMusic.playing=false
bgMusic.file_name = "../../music/"+fe.game_info(Info.Title)+".mp3"
bgMusic.playing=true
bgMusic.loop=true
break;
}
return false;
}
fe.add_transition_callback( "bgmusic_transitions" );
En este caso utiliza una funcion para poder hacerlo funcionar.
De momento no me detengo mucho en explicar como crearlas xq tampoco soy un experto
Una parte muy importante es usar "fe.game_info" las funciones no pueden usar "magic tokens" hasta donde yo se , por eso debemos darle el nombre del juego y su extension usando este parametro:
fe.game_info(Info.Title)+".mp3"
Tal como fue creada la funcion buscaria la cancion con el mismo nombre del juego en una carpeta "music" que estaria en la raiz de la instalacion de AM.
bgMusic.file_name = "../../music/"+fe.game_info(Info.Title)+".mp3"
Modificando esta parte por:
bgMusic.file_name = "music/"+fe.game_info(Info.Title)+".mp3"
Podriamos ponerla dentro de la carpeta del layout en una subcarpeta "music"
fe.add_text fe.load_moduleVoy usar el modulo "scrollingtext" de Liquid8b
http://forum.attractmode.org/index.php?PHPSESSID=7tLoV3vG9uvbHjNbHli112&topic=300.msg2189#msg2189Funciona todo mas o menos como vengo explicando , asi es como lo tengo configurado en el layout Basic:
/////////////
//Scroll Text
fe.load_module("objects/scrollingtext");
ScrollType.HORIZONTAL_LEFT);
local scroller = ScrollingText.add("[Title]", 400, 420, 150, 50, ScrollType.HORIZONTAL_LEFT);
scroller.settings.fixed_width= 280;
scroller.settings.loop =100;
scroller.set_rgb ( 0, 16, 150 );
scroller.text.charsize = 18;
scroller.settings.speed_x = 1;
scroller.text.font = "BEYNO";
La unica "novedad" , seria esta:
fe.load_module("objects/scrollingtext");
El modulo viene por defecto en la instalacion de AM en la carpeta "modules/objects" , por eso hay que cargarlo añadiendo "objects"
Funciona de la siguiente forma:
local scroller = ScrollingText.add("[Title]", 400, 420, 150, 50, ScrollType.HORIZONTAL_LEFT);
"scroller" esto tiene que ser "fijo" xq es como el modulo reconoce que queremos usar un texto scroll.Luego lo de siempre , magic token "Title" , posicion y tamaño y el tipo de "Scroll"
Si abrimos el "scrollingtext.nut" tenemos mas informacion:
// Requirements:
// the modules/objects/scroller directory along with this module
//
// Example:
// local scroller = ScrollingText.add( "[Title]", 0, 0, 500, 30 );
// scroller.set_bg_rgb( 255, 255, 255 ); //wrapper function to set scroller background
// scroller.set_rgb( 200, 0, 0); //wrapper function to set text color
// //some settings can be modified
// scroller.settings.delay = 250;
// scroller.settings.loop = 5; //fixed loop count
Son las opciones de fe.add_text mas las propias del modulo.
fe.add_listbox AnimationUno de los themes con las lisbox mas chula que tengo visto es el gamestation.
Usa una "funcion" para ocultar y mostrar lista.
//Game List Animation
::OBJECTS <- {
wheelLogo = fe.add_artwork("wheel", flx*0.025, fly*0.03, flw*0.23, flh*0.13),
logo = fe.add_image("logo.png", flx*0.0265, fly*0.03, flw*0.23, flh*0.13 ),
marquee = fe.add_artwork("marquee", flx*-0.2, fly*0.67, flw*0.18, flh*0.1),
gameListBG = fe.add_image ("black.png",flx, 0, flw*0.6, flh),
gameListTitle = fe.add_text("[Title]", flx, fly*0.055, flw*0.05, flh*0.1),
gameListBox = fe.add_listbox( flx, fly*0.171, flw*0.45, flh*0.65 ),
gameListList1 = fe.add_text("[ListSize]",flx, fly*0.88, flw*0.3, flh*0.1),
gameListList2 = fe.add_text("[ListEntry]",flx, fly*0.83, flw*0.3, flh*0.1),
gameListList3 = fe.add_text("[ListEntry]/[ListSize]",flx*0.76, fly*0.465, flw*0.3, flh*0.06),
moveStrip = fe.add_artwork("flyer2", flx*-1, fly*0.8, flw, flh*0.163 ),
}
::OBJECTS["marquee"].trigger = TRIGGER;
::OBJECTS["moveStrip"].trigger = TRIGGER;
//Animation for Global & Expert Mode
local move_shrink1 = {
when = Transition.ToNewList ,property = "scale", start = 1.8, end = 1.0, time = 1500, tween = Tween.Bounce
}
local move_shrink2 = {
when = Transition.ToNewSelection ,property = "scale", start = 1.8, end = 1.0, time = 1500, tween = Tween.Bounce
}
local move_marquee1 = {
when = Transition.ToNewSelection ,property = "x", start = flx*-0.3, end = 0, time = 900
}
local move_marquee2 = {
when = Transition.ToNewSelection ,property = "x", start = 0, end = flx*-0.3, time = 1600, delay = 3600
}
local move_strip1 = {
when = Transition.ToNewSelection ,property = "x", start = flx*-1 end = flx*0, time = 3000, delay = 3600
}
local move_strip2 = {
when = Transition.ToNewSelection ,property = "x", start = flx*-1 end = flx, time = 1, delay = 1
}
local move_gameListBG1 = {
when = Transition.ToNewSelection ,property = "x", start = flw, end = flx*0.59, time = 1
}
local move_gameListBG2 = {
when = When.ToNewSelection ,property = "x", start = flx*0.59, end = flw, time = 600, delay=1000
}
local move_gameListTitle1 = {
when = Transition.ToNewSelection ,property = "x", start = flw, end = flx*0.605, time = 1
}
local move_gameListTitle2 = {
when = When.ToNewSelection ,property = "x", start = flx*0.605, end = flw, time = 580, delay=1000
}
local move_gameListBox1 = {
when = Transition.ToNewSelection ,property = "x", start = flw, end = flx*0.59, time = 1
}
local move_gameListBox2 = {
when = When.ToNewSelection ,property = "x", start = flx*0.6, end = flw, time = 595, delay=1000
}
local move_gameListList1 = {
when = Transition.ToNewSelection ,property = "x", start = flw, end = flx*0.719, time = 1
}
local move_gameListList2 = {
when = When.ToNewSelection ,property = "x", start = flx*0.719, end = flw, time = 500, delay=1000
}
local move_gameListList3 = {
when = Transition.ToNewSelection ,property = "x", start = flw, end = flx*0.68, time = 1
}
local move_gameListList4 = {
when = When.ToNewSelection ,property = "x", start = flx*0.689, end = flw, time = 528, delay=1000
}
//Animation
animation.add( PropertyAnimation( OBJECTS.gameListBG, move_gameListBG1 ) );
animation.add( PropertyAnimation( OBJECTS.gameListBG, move_gameListBG2 ) );
animation.add( PropertyAnimation( OBJECTS.gameListTitle, move_gameListTitle1 ) );
animation.add( PropertyAnimation( OBJECTS.gameListTitle, move_gameListTitle2 ) );
animation.add( PropertyAnimation( OBJECTS.gameListBox, move_gameListBox1 ) );
animation.add( PropertyAnimation( OBJECTS.gameListBox, move_gameListBox2 ) );
animation.add( PropertyAnimation( OBJECTS.gameListList1, move_gameListList1 ) );
animation.add( PropertyAnimation( OBJECTS.gameListList1, move_gameListList2 ) );
animation.add( PropertyAnimation( OBJECTS.gameListList2, move_gameListList3 ) );
animation.add( PropertyAnimation( OBJECTS.gameListList2, move_gameListList4 ) );
OBJECTS.gameListList3.visible = false;
if ( my_config["wheel_logo"] == "Wheel + System" ){
OBJECTS.logo.visible = true;
OBJECTS.wheelLogo.visible = true;
}
else if ( my_config["wheel_logo"] == "System Only" ){
OBJECTS.logo.visible = true;
OBJECTS.wheelLogo.visible = false;
}
else if ( my_config["wheel_logo"] == "Wheel Only" ){
OBJECTS.logo.visible = false;
OBJECTS.wheelLogo.visible = true;
}
if ( my_config["enable_strip"] == "No" ){
OBJECTS.moveStrip.visible = false;
}
animation.add( PropertyAnimation( OBJECTS.wheelLogo, move_shrink1 ) );
animation.add( PropertyAnimation( OBJECTS.wheelLogo, move_shrink2 ) );
animation.add( PropertyAnimation( OBJECTS.logo, move_shrink1 ) );
animation.add( PropertyAnimation( OBJECTS.logo, move_shrink2 ) );
animation.add( PropertyAnimation( OBJECTS.marquee, move_marquee1 ) );
animation.add( PropertyAnimation( OBJECTS.marquee, move_marquee2 ) );
animation.add( PropertyAnimation( OBJECTS.moveStrip, move_strip2 ) );
animation.add( PropertyAnimation( OBJECTS.moveStrip, move_strip1 ) );
OBJECTS.gameListTitle.alpha = 230;
OBJECTS.gameListBG.alpha = 235
OBJECTS.gameListBox.charsize = 28;
OBJECTS.gameListBox.align = Align.Left;
OBJECTS.gameListBox.rows=9;
OBJECTS.gameListBox.set_sel_rgb( 240, 240, 240 );
OBJECTS.gameListBox.set_selbg_rgb( bgRed, bgGreen, bgBlue );
OBJECTS.gameListBox.set_rgb( 205, 205, 205 );
OBJECTS.gameListList1.align = Align.Right;
OBJECTS.gameListList1.alpha = 20;
OBJECTS.gameListList2.set_rgb( bgRed, bgGreen, bgBlue );
OBJECTS.gameListList2.align = Align.Right;
OBJECTS.gameListList2.alpha = 140;
Parece un lio descomunal al principio xq ademas de la lista le añade varias animaciones de otros objetos , pero seria sencillo dejar solo la lista si nos interesase ponerla en nuestro Basic.
gameListBox = fe.add_listbox( flx, fly*0.171, flw*0.45, flh*0.65 ),
Aprovecho para comentar esta parte:
flx, fly*0.171, flw*0.45, flh*0.65
Esto se usa para crear layouts "responsive" que se adapten a diferentes pantallas
Para que funcione correctamente necesitamos este codigo al principio del layout:
local flx = fe.layout.width;
local fly = fe.layout.height;
local flw = fe.layout.width;
local flh = fe.layout.height;
Voy dejar un ejemplo un poco mas sencillo que hice para mi rpi zero:
// Title
local title = fe.add_text("[Title]", 10, 595, 600, 50);
title.align = Align.Left;
title.charsize = 31;
title.set_rgb(255, 255, 255);
title.alpha = 0;
//title.style = Style.Underlined;
local title_alpha_cfg_on_load = {
when = When.StartLayout,
when = Transition.ToNewList,
property = "alpha",
start = 0,
end = 255,
time = 1000
}
animation.add( PropertyAnimation( title, title_alpha_cfg_on_load ) );
local title_shrink_cfg_on_load = {
when = When.StartLayout,
when = Transition.ToNewList,
property = "scale",
start = 0.1,
end = 1.0,
time = 2000
tween = Tween.Quad,
}
animation.add( PropertyAnimation( title, title_shrink_cfg_on_load ) );
local title_alpha_cfg = {
when = Transition.ToNewSelection ,
property = "alpha",
start = 0,
end = 255,
time = 1000
}
animation.add( PropertyAnimation( title, title_alpha_cfg ) );
local title_shrink_cfg = {
when = Transition.ToNewSelection ,
property = "scale",
start = 0.1,
end = 1.0,
time = 2000
tween = Tween.Quad,
}
animation.add( PropertyAnimation( title, title_shrink_cfg ) );
/////////////////////
local gamelist = fe.add_listbox( -1000, 400, 700, 400 );
gamelist.sel_green = 255;
gamelist.sel_blue = 255;
gamelist.sel_red = 255;
gamelist.sel_alpha = 0;
gamelist.selbg_alpha = 0;
//gamelist.sel_style = Style.Underlined;
gamelist.set_rgb( 118, 118, 118 );
gamelist.charsize = 30;
gamelist.align = Align.Left;
gamelist.rows = 10;
local gamelist_slide_start_cfg = {
when = When.StartLayout,
property = "x",
start = -1000,
end = 10
time = 1500
tween = Tween.Quad,
}
animation.add( PropertyAnimation( gamelist, gamelist_slide_start_cfg ) );
Solamente lleva una pequeña animacion cuando inciamos el layout y cuando nos movemos entre los juegos otra unicamente para el juego seleccionado:
Basicamente , ocultamos una parte del listbox con este codigo:
gamelist.sel_green = 255;
gamelist.sel_blue = 255;
gamelist.sel_red = 255;
gamelist.sel_alpha = 0;
gamelist.selbg_alpha = 0;
Y con esta parte añadimos el juego seleccionado usando otro objeto y que parezca que forma parte de la lista
local title = fe.add_text("[Title]", 10, 595, 600, 50);
Por si alguien quiere el fondo es este:
http://backgroundcheckall.com/wp-content/uploads/2017/12/arcade-background-12.jpg