martes, 25 de junio de 2019

Sombra Circular Para Imagen

Seguramente maquetando más de alguno se habrá vuelto loco a la hora de hacer una sombra circular a un icono, normalmente flotante. Para resolverlo la práctica más sencilla es tomando una sombra de tipo bitmap y posicionarla debajo de la imagen. Ésto podría servirnos si se plantea compatibilidad con navegadores viejos o que no soportan CSS3.


CSS3


En CSS3 disponemos de una serie de nuevas funcionalidades en las que se encuentra box-shadow , que sirve para crear sombras. Las sombras son para las etiquetas, que son cuadradas, pero ésto no es problema si lo combinamos con la propiedad border-radius, en la cual podemos indicar cuanto de redondo queremos que sean las esquinas de la etiqueta. La sombra generada se adaptará a la silueta de la etiqueta.

Algunas veces puede que la imagen escogida no encaje bien, para solucionar eso habría que prescindir de la etiqueta img y trabajar con el background-image, para asignar una imagen, el background-size, para configurar el tamaño de la imagen (no de la etiqueta) y por último hacer un background-position : center.

sábado, 15 de junio de 2019

La Chica De Junio


 Con ustedes Naomi Wu, alias sexycyborg, quien es además conocida por diversas facetas entre ellas la de promocionar productos electrónicos chinos en youtube. Es una apasionada de la tecnología, la impresión 3D y cuando puede luce palmito cosplayer sexy también. Inteligente y sexy, para mi la mujer perfecta 😍


viernes, 14 de junio de 2019

Framework Minimalista MVC En Php

 Bueno, antes de comenzar hablar sobre el tema de la entrada o publicación quisiera hablar de otra cosa, más que nada para desahogarme un poco, porque es un tema que me ha repateado desde que he comenzado recientemente en el mundo corporativista de las empresas. Yo anteriormente vengo de realizar desarrollos freelance/autónomo, en teoría un portafolio debería ser prueba inequívoca de que sabes moverte en el mundo de la programación y si a eso le sumas que tienes estudios oficiales relacionados con el desarrollo de aplicaciones pues yo creo que no cabe duda que es así. El proyecto que presento es prueba de que ésto no es así, las empresas exigen a los candidatos a un puesto de trabajo pruebas y entrevistas que para mi rayan un poco el absurdo, si a eso le sumas que después de exigir una prueba ya no es que te rechacen por hacerla mal desde el punto personal de la persona que se encarga de seleccionar sino peor aun, no te comunique en que punto del proceso te encuentras, no conteste o se haga el loco. Yo desde las dos pruebas realizadas, bastante complicadas por cierto, nunca volveré a realizar ninguna más. Para entender lo absurdo de la cuestión, usted cuando contrata un electricista o un fontanero ¿le hace alguna prueba? le dice, mire monte un grifo antes de contratarlo y si ya, pues ya veremos si lo contratamos(hay como diez fontaneros haciendo la prueba, montando grifos para demostrar su pericia). Pues eso pasa o me ha pasado.

 Éste proyecto como antes comenté fue para demostrar que estaba al tanto del funcionamiento de un modelo MVC en este caso con Php, no bastaba que supiera Laravel o Symfony, quería demostrar que además de saber trabajar con los frameworks más conocidos también sabía como funcionaban interiormente, que no sólo me dedico a picar código (que de vez en cuando lo hago), sino que también puedo hacer uno. Claro que hacer un framework bien hecho con todas sus tonterías toma mucho trabajo y como siempre ¿por qué reinventar la rueda? pues eso, aquí como lo que se mostró el otro día en la versión front es puramente de propósito educativo. Y bueno, si alguien les pide una prueba para algún trabajo como a mi pues por qué no copiarlo.

Framework MVC y enrutador


 Un marco MVC, modelo, vista y controlador, es un marco actualmente muy extendido en los grandes desarrollos, como contamos en la entrada anterior es un patrón de diseño que mejora la organización y mantenimiento del programa obteniendo mejores resultados en tecnologías que soportan la programación orientada a objetos como es el caso de java

 Normalmente los frames de desarrollo web que soportan MVC disponen de un sistema para enrutar, ésto significa que permiten definir rutas que son direccionadas desde la página principal a sus convenientes vistas. Ésto se realiza mapeando asociativamente las rutas con las vitas o controladores de vistas. Para éste caso, como se muestra abajo, se ha usado vistas con código embebido, pero perfectamente podría haber sido un controlador compuesto por una clase con varios métodos y que retornara una página tal como hacen por ejemplo Spring o Symfony 4.
$request = filter_input(INPUT_SERVER,'REQUEST_URI'); 
$rutas = ["/"         => "indice"  , // MAPA
          "/login"    => "login"   ,
          "/registro" => "registro",
          "/salir"    => "salir"   ,
          "/admin"    => "admin"   ,
          "/home"     => "home"    ];

if (array_key_exists($request, $rutas)!=false){
   require "Vistas/$rutas[$request].php"; // Redireccionamos

Estructura de ficheros


 Para una buena organización es recomendable o mejor dicho deseable sobre todo para este propósito disponer de una estructura intuitiva de directorios. Lejos de lo que algunos puedan imaginar, al final los controladores, vistas y modelos son simplemente ficheros que internamente tendrán quizás que disponer de un código adicional según el caso pero que suelen ser clases o código que deberá estar anclado en el espacio de trabajo(namespace, package, etc...) de la aplicación para poder estar localizado cuando sea requerido.

 En mi caso opté por crear una estructura similar a las empleadas por muchos frames Php conocidos, en la raíz el index.php (el enrutador) y luego tres directorios principales, modelos, vistas y controladores. 


Sobre el proyecto


 Para este ejemplo sólo se usaba un modelo, un usuario, y varios controladores que permiten llevar el registro de la cuenta de un usuario y acceso, con posibilidad de trabajar con roles. El sistema incluye control de sesiones artesanal, en plan cutre, y un sistema de verificación vía correo electrónico que provee la librería PHPMailer.

 El proyecto como siempre disponible en mi Github, cualquier duda hacérmela saber e intentaré en la medida de lo posible aclararla. No olviden que si quieren probarla deben configurar la información de la base de datos y correo electrónico.

 Bueno ésto es todo, ahora posiblemente me desapareceré un par de meses buenos trabajando con otras cosas que si tengo posibilidad ya contaré en siguientes entradas. Mañana puede que publique la chica del mes 😁que ya llevo tiempo sin presentar a ninguna y en este blog también se habla de mujeres y a quien no le guste que se aguante 😤

miércoles, 12 de junio de 2019

FrameWork Sencillo En VanillaScript O Algo Parecido


 Buenas, pues aquí estamos, a piñón con el desarrollo Web, aunque no es de mis pasiones a pesar de haberlo estudiado, más que nada porque no había otra cosa que estudiar, pues es importante para mi de cara al trabajo que desempeñaré. Espero que con experiencia algún día pueda saltar a otras ramas del desarrollo.

 Vale, pues lo que les traigo hoy aquí, es un sencillo framework con propósito meramente educativo, no se trata de reinventar la rueda, pero es importante tener un conocimiento de como funcionan esas cosas tipo Vue JS, React, Angulares y demás, que intentan facilitar el desarrollo en el frontend por medio de un marco de trabajo modular, que permita implementar la aplicación de forma organizada y modificar los módulos de éste sin mucho costo.

Etiquetado personalizado y componentes


 Este tipo de frames, los citados anteriormente, destacan por el uso de los llamados componentes, digamos que la filosofía es llevar la programación orientada objetos a límites insospechables en el front integrando objetos que tengan parte lógica, funcional, propiedades o atributos y una vista o plantilla que les confiera en resumen una independencia del resto de componentes pero que permita integrarse conjuntamente con todo.

 En el ejemplo que mostraré abajo de nuestro componente se trata simplemente de una estructura, que bien podría ser una clase, que muestra las características descritas. 


{ "etiqueta": {
                body: {
                    campo1: 'soy el campo1',
                    campo2: 'soy el campo2'
                },
                template: "<h1> {{ campo1 }} / {{ campo2 }} </h1>" }

 Como se puede apreciar arriba, hemos definido una propiedad template para nuestro componente que define como será visualmente, la plantilla, así como un nombre de etiqueta que representará al componente tanto en nuestro html como cuando nos queramos referir a éste en el programa.

 Dentro de la propiedad body estarán los atributos de la plantilla, que estarán vinculados al render, de esta forma se diseñará para que cuando trabajemos con el componente nos olvidemos de la parte que actualiza el html. Prácticamente ésto nos permitirá ocuparnos solamente de la funcionalidad del componente.

 En muchos de los frames se facilitan instrucciones embebidas en las etiquetas, tipo como for o if, ésto no está contemplado en la publicación porque simplemente no he querido generar mucha complejidad. Para los que estén interesados en saber como se haría les diré que simplemente se trata de definir propiedades a las etiquetas y en los valores se toma el resto de instrucciones y los valores o argumentos. Claro que después hay que incluirlo, pero no es difícil. Ejemplo:

<etiqueta for="let i=0 to 10"></etiqueta>


Estructura principal e integración de los componentes

 Como vamos a tener todo organizado vamos a definir nuestro marco de trabajo, framework, con el nombre de app aunque podría ser cualquier nombre. Nuestro marco de trabajo incluirá una parte donde se indicarán los componentes, llamada igual, que existirán en el programa, instanciados en la página. Digamos que la parte del código es lo que representa o define el componente mientras que su instancia la llevará a cabo el motor del frame al examinar la página del programa.

 Por último la parte del main, es el ámbito donde trabajaremos con las estancias que estarán generadas como se dijo por el frame, invisible para nosotros. En dicha parte es donde definiremos el programa y el comportamiento de los componentes, por ejemplo definir un evento para que haga algo, como un click, o cualquier cosa.

 Ejemplo de la página:

<head>
    <meta>
    <style>
        etiqueta {
            background: red;
            display: block;
        }
    </style>
</head>

<body>
    <h1>Hola mundo</h1>
    <etiqueta></etiqueta>
    <etiqueta></etiqueta>
</body>

 El código en nuestro script:


app = {
    componentes: [{
        "etiqueta": {
            body: {
                campo1: 'soy el campo1',
                campo2: 'soy el campo2'
            },
            template: "<h1> {{ campo1 }} / {{ campo2 }} </h1>"
        }
    }],
    main() {
        this.etiqueta[0].campo1 = "Soy un frame sencillo sin mucha ambición";
        this.etiqueta[1].click = function() {
            alert("Hola holita");
        };
    }
}


Para no complicar la cosa, el motor genera las instancias en un array con el nombre de la etiqueta. Por ejemplo si agregáramos otro componente llamado listado y sólo hubiera una instancia en la página simplemente accederíamos a ella en el programa como listado[0]. En el caso que exponemos en el ejemplo observamos que tenemos un componente etiqueta definido en componentes y en la página tenemos dos instancias de este por eso accedemos con etiqueta[0] para el primero, orden descendente (luego veremos por qué), y al segundo componente accedemos por etiqueta[1].


Motor del framework


 El engine o motor es la parte que no se ve, es la que normalmente se llama por medio del enlace pertinente. Lo ideal sería crearse un código ofuscado del motor y vincularlo, así la página estaría más clara y sólo trabajaríamos con la estructura del frame.

 Para desarrollar este muy sencillo framework sólo vamos a requerir de una función recursiva que nos permitirá navegar por los nodos de forma amistosa. A la función le vamos a pasar el nombre de la etiqueta que queramos localizar y asignarle una acción.

// Herramienta
function buscaTag(nodo, tag, action, retorno) {
    tag = tag.toUpperCase();
    nodo.childNodes.forEach((item) => {
        if (tag == item.nodeName) {
            if (retorno) return action(item);
            action(item);
        }
        buscaTag(item, tag, action);
    });
}



 Luego habrá que inicializar el framework. En esta parte se comprueban los componentes disponibles y se instancian los componentes para que estén accesibles en el programa. En el código he usado la función eval(), para instanciar, pero puede hacerse de otra forma, eso es a gusto del consumidor.


// inicializadomos!!
buscaTag(document.getRootNode(), "html", function(item) {
    app.html = item;
}, true);
// Examinamos los componentes disponibles y creamos las instancias de estos
app.componentes.forEach(componente => {
    var i = 0;
    var nombreComponente = Object.keys(componente)[0];
    app[nombreComponente] = [];

    // Instanciamos componentes
    buscaTag(document.getRootNode(), nombreComponente, function(item) {
        item.id = nombreComponente + i;
        eval("app." + nombreComponente + "[" + i + "]=" + JSON.stringify(componente[nombreComponente].body));
        i++;
    }, false);
});
// Ejecutamos el programa
app.main();

 Y por último tenemos la parte que actualiza periódicamente. Como podrán observar las propiedades renderizables de las plantillas se buscan por medio de una sencilla expresión regular y luego se sustituye con el valor acorde que tenga el componente en ese momento. Aunque parezca todo muy estático podemos comprobar por ejemplo mediante la consola del navegador como es posible acceder a la aplicación por medio del objeto app y modificar la función click() de cualquiera de los dos componentes existentes en el ejemplo o cambiar el contenido de los campos que en un segundo estará todo actualizado.


// Actualizamos!! (cada segundo)
window.setInterval(() => {
    /////////////////////////////////////////////////////
    app.componentes.forEach(componente => {
        var nombreComponente = Object.keys(componente)[0],
            appComponente = componente[nombreComponente],
            i = 0;

        buscaTag(app.html, nombreComponente, function(item) {
            componente = app[nombreComponente][i];
            componente["render"] = appComponente.template;

            // sustituimos los atributos por sus valores
            Object.keys(appComponente.body).forEach(atributo => {
                componente.render = componente.render.replace(
                    new RegExp("({{)+[\\s](" + atributo + ")+[\\s]+(}})", "g"), componente[atributo]);
            });

            // introducimos el render
            let etiqueta = document.getElementById(nombreComponente + i);
            if (etiqueta.innerHTML !== componente.render) {
                etiqueta.innerHTML = componente.render;
            }

            // Añadimos propiedades especiales como eventos ...
            var elementoDom = document.getElementById(item.id);
            elementoDom.parentNode.replaceChild(item.cloneNode(true), item); // Eliminamos eventos
            if (app[nombreComponente][i].click !== undefined) {
                document.getElementById(item.id).addEventListener("click", app[nombreComponente][i].click);
            }

            i++;
        }, false);
    });
}, 1000);

 Como ven todo ésto de los frameworks no es magia y sólo se trata de una especie de patrón de diseño para organizar mejor el desarrollo y mantenimiento de la aplicación. Quizás en otra ocasión con tiempo pueda mostraros lo mismo pero en la parte del backend, en Php of course.

  Si quieren cacharrear subo el fichero a mi espacio Github para que piquen y hagan experimentos, que lo disfruten y me dicen si quieren que la próxima entrada sea el framework de Php o comenten alguna sugerencia. Bye.

sábado, 3 de febrero de 2018

La chica de febrero

 Lleva mucha ropa porque hace frío todavía, aquí por lo menos en el hemisferio norte. Habrá que esperar a la primavera señores.




Algoritmo de búsqueda

 Buenas. Pues nada el otro día pensando que cosas meter en este blog que me puedan ser útiles para mi o para otras personas, ya que no tengo discípulos, me acordé de un algoritmo que recientemente implementé pero que fue desarrollado hace long time ago (más de una década), a poco de comenzar en DarKBasic (un engine para crear juegos en Basic). Dicho algoritmo es simplemente comprender la idea, apenas mostraré código, quizás si porque ya lo tengo implementado pero sólo basicamente y con lo de basicamente me refiero a no una forma compleja a la que puede llegar. El algoritmo en si no solamente sirve para hacer búsquedas, mientras lo desarrollaba con boli y papel (así es como se crean los algoritmos) me di cuenta que puede usarse para rellenar un polígono (dentro de una matriz dimensional) entre otros posibles propósitos. 

 Cuando hablo de búsquedas me refiero a completar una ruta desde un punto A a otro punto B. No me refiero a las consultas desde luego, eso no tiene mérito ninguno aunque se de alguien muy entendido en base de datos que me diría que las consultas de datos son algo pero que muy complejo, cosa que no estoy de acuerdo pues desde mi punto de vista lo complejo es para quienes no comprenden como funciona algo. Comprender tampoco es que necesariamente tengas que aprenderte de puntillas (de la A a la Z) todo el proceso, todos los pasos, los nombres, fechas o hitos históricos, algo que normalmente es como funciona la educación o los métodos educativos ¿Por qué esta énfasis en lo de comprender? Porque a pesar de que usted, lector de esta publicación, pierda el código fuente o nunca pueda recuperar esta página para consultar el algoritmo, típico en los pica-códigos (tranquilo yo también empecé así), siempre que comprenda como funciona podrá desarrollar el algoritmo, tal como me ha pasado.


La teoría del buscarutas

 Cuando desarrollé el algoritmo lo llamé buscarutas porque principalmente ese era su propósito. Su deber era trazar una ruta desde un punto A hasta otro punto B, en su recorrido podría encontrarse con lugares no ya restringidos sino también casi cerrados (o cerrados, no hay ruta posible). Así es como me vino a la cabeza, aunque fue algo visual. Me vino como conseguiría llegar a otro punto que estuviera fuera de un vaso o con forma de vaso. Pensé en el agua, el agua cuando llena el vaso se desborda. Si el problema solamente fuera ese, llenar el vaso... Y así fue como empecé, el algoritmo primigenio inundaba la matriz con unos datos que se comportaría como el agua hasta que esta tocara el otro punto.

 Para inundar la matriz simplemente se comienza desde un punto y se comprueba si hay salida a las celdas próximas, de estar estas vacías o no encontrarse un obstáculo se llena la celda con un dato. En principio se usaba un dato que significaba que estaba ocupado llena esa celda pero luego se optó por un método numérico.

 Este proceso, el de inundar se hace recursivamente. Esto significa que cada celda comprobará a su vez que sus celdas próximas estén vacías y de no estarlo las rellenará indiferentemente de si esas celdas se alejan del destino o el origen, ya que es necesario inundar la superficie para tener claro los límites, salidas o caminos posibles. Dese cuenta querido lector que el algoritmo está diseñado para que afronte con éxito una ruta que lo saque del laberinto más enrevesado, y esto es literal, no hablo metafóricamente.

 Si en el desarrollo optamos por una depuración visual de la matriz (dimensional) podríamos ver un resultado así:


 Llegado a este punto, tenemos algo que de alguna forma llega hasta el otro punto, valga la redundancia. Pero lo que nos interesa es que aparte de encontrar el camino lo genere porque así a priori lo que tenemos es un sistema que nos puede indicar que existe un camino o que también podríamos usar para rellenar polígonos, por ejemplo. Para resolver el siguiente punto me tomó varios días, pensando y garabateando sobre el papel hasta llegar a la conclusión de que era necesario un índice, algo que indicara además que después de un número iba otro número, pero ¿Bajo que regla o reglas? ¿La distancia? La verdad es que el sistema apareció de una forma que no recuerdo bien, pero es cierto que empezó como un índice. El código usado consistía en lo siguiente, se trataba de valores numéricos que ascendían, se incrementaban según se inundaba la superficie, los valores crecían y crecían y por alguna razón, no me acuerdo sinceramente porque llegué a esta conclusión o si lo sabía os juro que no recuerdo en este instante (más de diez años de eso), decidí tomar el valor más grande para trazar la ruta o camino y luego buscar el valor más pequeño que me señalaría al origen (siempre de mayor a menor).


 Y así amigos fue como conseguí algo tan crucial como crear un mapa 3D y que una entidad 3D llegara al objetivo aunque este cambiara su posición en el mapa, sin atorarse o quedándose caminando infinitamente hacia la pared como un gilipollas. El algoritmo originalmente trabajaba con desplazamiento diagonal pero para un trabajo reciente se me pedía que el desplazamiento solo fuera en cruz, como el movimiento de la torre en ajedrez y la verdad no me supuso ningún problema adaptarlo. Por eso si domináis bien esta técnica no es que paséis a cinturón negro de programación pero podréis resolver montón de problemas, incluso quien sabe, redes neuronales (ahora tan de moda).

Aplicación práctica (ejemplo)

Aquí una porción de una aplicación desarrollada en VanillaScript. La porción recoge como primero se encuentra el camino, la inundación, y la segunda parte más pequeña la que genera el camino y lo guarda en un array. En ambos caso se usan bucles indeterminados, aunque no falta decir que para evitar el cuelgue o la aplicación no responde etc... usar un contador para impedir que se quede en un bucle infinito. Cuando este contador llegue a cero se podría interpretar que no hay caminos posibles.

        var ruta=[];
        // creamos caminos
        movimientos=0;
        ruta[0]=[hastaX, hastaY,0];
        this.mapa=replaceAt(this.mapa, hastaY*this.anchoMapa+hastaX,movimientos); 
        this.mapa=replaceAt(this.mapa, desdeY*this.anchoMapa+desdeX," "); 
        var bucle=100;
        while(encontrado!=true && bucle>0){
            bucle--;
            for (var i in ruta){
                var punto=ruta[i];
              
                if (punto[2]==0){
                    ruta[i]=[punto[0],punto[1],1];
                    
                    if (this.mapa[punto[1]*this.anchoMapa+(punto[0]-1)]==" ") { 
                        movimientos++;
                        ruta[movimientos]=[punto[0]-1, punto[1],0];
                        this.mapa=replaceAt(this.mapa, punto[1]*this.anchoMapa+(punto[0]-1),"*");                   
                        if (ruta[movimientos][0]==desdeX && ruta[movimientos][1]==desdeY){
                            encontrado=true;
                            break;
                        }
                    }
                    if (this.mapa[(punto[1]-1)*this.anchoMapa+punto[0]]==" ") { 
                        movimientos++;
                        ruta[movimientos]=[punto[0], punto[1]-1,0];
                        this.mapa=replaceAt(this.mapa, (punto[1]-1)*this.anchoMapa+punto[0],"*");                  
                        if (ruta[movimientos][0]==desdeX && ruta[movimientos][1]==desdeY){
                            encontrado=true;
                            break;
                        }
                    }
                    if (this.mapa[punto[1]*this.anchoMapa+(punto[0]+1)]==" ") { 
                        movimientos++;
                        ruta[movimientos]=[punto[0]+1, punto[1],0];
                        this.mapa=replaceAt(this.mapa, punto[1]*this.anchoMapa+(punto[0]+1),"*");
                        if (ruta[movimientos][0]==desdeX && ruta[movimientos][1]==desdeY){
                            encontrado=true;
                            break;
                        }
                    }
                    if (this.mapa[(punto[1]+1)*this.anchoMapa+punto[0]]==" ") { 
                        movimientos++;
                        ruta[movimientos]=[punto[0], punto[1]+1,0];
                        this.mapa=replaceAt(this.mapa, (punto[1]+1)*this.anchoMapa+punto[0],"*");
                        if (ruta[movimientos][0]==desdeX && ruta[movimientos][1]==desdeY){
                            encontrado=true;
                            break;
                        }
                    } 
                }               
            }
        }
        
        var ruta_final=[];
        if (bucle!=0) { // generamos ruta o camino
            for (var i=movimientos;anterior!=i;){
                var punto=ruta[i], anterior=i;
                for (var ii=i-1;ii>0;ii--){
                    var siguiente=ruta[ii];
                    if ((Math.abs(punto[0]-siguiente[0])==1 && Math.abs(punto[1]-siguiente[1])==0) ||
                        (Math.abs(punto[0]-siguiente[0])==0 && Math.abs(punto[1]-siguiente[1])==1)){
                        i=ii;
                        ruta_final.push(ruta[i]);
                        break;
                    } 
                }
            
            }
            ruta_final.push(ruta[0]);
        }


martes, 16 de enero de 2018

Las consolas se mueren

 Pues si. Lamento ser tan dramático con el titular pero hace meses que le doy vueltas a este asunto tan preocupante porque esas cajas de diversión que comenzaron hace tantísimos años tienen el tiempo contado.

¿Pero cómo cojones hemos llegado a ésto?

 Son varios factores en mi opinión y aquí los enumero, aunque es posible que falten algunos porque ya digo esta es mi opinión que nace de la experiencia, muchos años de vicio:
  • Desarrollos cada vez más caros. Si, el caso es que GNU está presente en el PC pero en las multiples plataformas de videojuegos no. Eso y que cada vez las consolas son más complejas hacen que invertir tiempo para crear tú propia librería por medio de la ingeniería inversa sea casi una pérdida de tiempo y que cueste más que comprar una licencia para publicar juegos para determinada consola usando cualquiera de los montones de motores disponibles, tipo Unity o Unreal por mencionar los más populares.
  • Público más exigente, que se puede traducir en que cada vez un listón más alto, porque no es lo mismo sacar el tetris para PS4 que aparte haría desmerecer la potencia del cacharro. Lo que está claro es que queremos juegos cada vez con más filigranas y a la vez muy adictivo, y eso se traduce en un equipo de desarrollo relativamente grande y de ahí se podría pasar al primer punto, un mayor gasto. Tiempo atrás quedó cuando un programador podía hacer la música, los gráficos y el juego mismo!!
  • La estafa de los DLC, ampliaciones, expansión, extensiones o como coño quieran llamarlo. Si, ahora lo que da dinero no es crear un juego sino crear el juego en cachitos, y por supuesto, vendiendo cada cachito de tal forma que la suma de todos los cachos valgan el doble de lo que originalmente se vendería el juego completo solo.
  • Un mercado cada vez más errático debido a los factores citados, que dicho de forma llana, sino hay juegos o pocos en una plataforma los jugadores tarde o temprano la abandonan.
  • Actualizaciones infinitas y juego online por cojones, y de esto experimentando hace unos días y que fue la gota que culminó el vaso que me ha llevado a escribir esta entrada. Os lo cuento para queden flipando. Adquirí hace tiempo un juego de Ubi soft, el For honor, tuve un problema con la cuenta de Ubi soft (el primer día) y nunca más volví a poder jugarlo pues me quedé a la espera de que ese soporte tan gentil (malditos hijoputas prepotentes) me solucionaran el problema. Es un juego por cojones ya no es suficiente que estés conectado con tú cuenta de PS4 sino va más lejos aun y solo funciona conectado y con cuenta de usuario Ubi Soft, a joderse se ha dicho porque yo lo valgo, más o menos así habrán dicho el máximo representante de Ubi Soft con esta absurda política. EEeeeh y que no he mencionado que aunque juegues online hay que hacer por cojones la instalación de tropecientos gigas en la memoria de la consola ¿Qué no tienes espacio? Pues no juegas o eliminas lo que tengas, o en el mejor de los casos para las tiendas te compras otro y no pasa nada (total unos pocos euros €€€). Pues esto dije, nunca más compro un juego de Ubi Soft, pues el For Honor a la semana lo descambié, y terminé comprando otra perla, el Destinity 2 de Bungie Studios. Emocionado llegué a casa y metí el juego, entonces la PS4 me indica que tiene que actualizarse, 3 gigas, bueno no pasa nada me dije. Una vez acabó de actualizar el juego pidió actualizarse porque sino no se ejecutaba, bueno no pasa nada me dije. YA cuando acabo, al cabo de unas horas, me dije por fin... y el juego nuevamente me indicó que tenía que volver a actualizarse, y todo esto para luego jugar a un juego con problemas en el servidor, pues hay que jugarlo conectado por cojones y con algunos bugs... en fin, alado sea el equipo Steam y el PC, saben a lo que me refiero?  

Alternativas al hambre de los jugadores


 La alternativa pasa bien o pasarte a la plataforma rival o competencia, la cual no es nada barata, pues las consolas han llegado a una política de precios casi absurda. O volver al PC, esa máquina que en lo que se refería a jugabilidad siempre había sido pobre pero que ahora con el abaratamientos de componentes y un mercado glorioso de portabilidades, únicos y de bajo presupuesto (indies), hacen que la máquina con más juegos y más entretenida sea el Personal Computer, elegido por la mayoría de jugadores o gamers. Porque ¿dónde verás emuladores de PS, Nintendo, Super Nintendo, Sega Megadrive y sin fin de máquinas de entretenimiento? pues en el PC sino.