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) ![Sonreir ;D](https://arcadespain.info/Foro/Smileys/akyhne/grin.gif)
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#new![](https://uploads.tapatalk-cdn.com/20180403/6b147bc7097564a6e957e48997ad1cf9.jpg)
Lo 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:
![](https://i.imgur.com/5pWynjx.png)
Y dentro obviamente metemos los logos
![Guiñar ;)](https://arcadespain.info/Foro/Smileys/akyhne/wink.gif)
![](https://i.imgur.com/44VMJvs.png)
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:
![](https://i.imgur.com/lwlRAmF.png)
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
![Sonrisa :)](https://arcadespain.info/Foro/Smileys/akyhne/smiley.gif)
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
![Sonreir ;D](https://arcadespain.info/Foro/Smileys/akyhne/grin.gif)
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
![Cheesy :D](https://arcadespain.info/Foro/Smileys/akyhne/cheesy.gif)
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"
![Guiñar ;)](https://arcadespain.info/Foro/Smileys/akyhne/wink.gif)
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
![Sonreir ;D](https://arcadespain.info/Foro/Smileys/akyhne/grin.gif)
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