{"id":46,"date":"2020-11-15T09:09:38","date_gmt":"2020-11-15T09:09:38","guid":{"rendered":"https:\/\/specnext.dev\/es\/?p=46"},"modified":"2020-12-25T11:27:50","modified_gmt":"2020-12-25T11:27:50","slug":"sprites-por-hardware-tutorial-2","status":"publish","type":"post","link":"https:\/\/specnext.dev\/es\/2020\/11\/15\/sprites-por-hardware-tutorial-2\/","title":{"rendered":"Sprites por Hardware \u2013 Tutorial 2"},"content":{"rendered":"\r\n<h5>Este es un extracto del art\u00edculo originariamente publicado en mi web <a href=\"https:\/\/lacavernainformatica.com\">lacavernainformatica.com<\/a><\/h5>\r\n<p>Bueno seguro que si ya hab\u00e9is visto y practicado con la <a href=\"https:\/\/specnext.dev\/es\/2020\/11\/14\/sprites-por-hardware-tutorial-1\/\">primera entrega<\/a>, tendr\u00e9is muchas ganas de seguir avanzando en la Programaci\u00f3n del NextBasic. Y es que todav\u00eda tenemos muchos m\u00e1s comandos y operaciones que podemos realizar sobre nuestros Sprites.<\/p>\r\n\r\n\r\n\r\n<p>Sobre todo en este tutorial de Programaci\u00f3n de Videojuegos en NextBasic para el Zx Spectrum Next, vamos a ver dos facilidades que nos brinda este nuevo lenguajes.<\/p>\r\n\r\n\r\n\r\n<ul class=\"wp-block-list\">\r\n<li>Movimiento automatizado de Sprites.<\/li>\r\n<li>Agrupaci\u00f3n de Sprites.<\/li>\r\n<\/ul>\r\n\r\n\r\n\r\n<p>Y os preguntar\u00e9is, \u00bfY en que nos puede beneficiar el hacer uso de estas caracter\u00edsticas?<\/p>\r\n\r\n\r\n\r\n<p>Pues vayamos por pasos. El movimiento automatizado nos puede resultar sumamente \u00fatil por ejemplo para realizar los movimientos de nuestro personaje, sin necesidad de estar controlando continuamente su posici\u00f3n, como hac\u00edamos en el <a href=\"https:\/\/github.com\/Nextric\/The-Octopus-Hunt\" target=\"_blank\" rel=\"noreferrer noopener\">The Hunting Octopus<\/a>. O por ejemplo, y como es el caso del juego <a href=\"https:\/\/github.com\/Nextric\/Darts\" target=\"_blank\" rel=\"noreferrer noopener\">Darts<\/a> sobre el que vamos a basar esta explicaci\u00f3n, nos permite lanzar un Sprite, en este caso un dardo, y olvidarnos relativamente de \u00e9l.<\/p>\r\n<p>\u00a0<\/p>\r\n\r\n\r\n\r\n<div class=\"wp-block-image\" style=\"text-align: center\">\r\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" class=\"wp-image-95 aligncenter\" src=\"http:\/\/lacavernainformatica.com\/wp-content\/uploads\/Darts.png\" alt=\"Darts Basic Videogame\" \/>\r\n<figcaption>Men\u00fa de inicio del juego Darts<\/figcaption>\r\n<\/figure>\r\n<\/div>\r\n\r\n\r\n\r\n<p>\u00a0<\/p>\r\n\r\n\r\n\r\n<p>Otra ventaja, es que al realizarse mediante hardware, no cargamos nuestra CPU con c\u00e1lculos de posiciones y dem\u00e1s tareas, permitiendo liberar bastante al Zx Spectrum Next de dichos procesos.<\/p>\r\n\r\n\r\n\r\n<p>\u00a0<\/p>\r\n\r\n\r\n\r\n<p>Y ahora me dir\u00e9is, muy bien yo le digo que vaya hacia la derecha, pero no controlo exactamente en que posici\u00f3n est\u00e1, porque no llevo un control de la misma.<\/p>\r\n\r\n\r\n\r\n<p>Pues para eso podemos hacer uso de dos comandos que veremos en detalle un poco mas adelante, que nos permiten dos cosas. Por un lado podemos preguntar en cualquier momento la posici\u00f3n de un Sprite en particular y por otro lado, podemos saber cuando dos o m\u00e1s Sprites han tenido una colisi\u00f3n. Todo esto repito, mediante Hardware.<\/p>\r\n<p>\u00a0<\/p>\r\n\r\n\r\n\r\n<div class=\"wp-block-image\" style=\"text-align: center\">\r\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" class=\"wp-image-96 aligncenter\" src=\"http:\/\/lacavernainformatica.com\/wp-content\/uploads\/Darts_shot.png\" alt=\"Darts shot Basic VideoGame\" \/>\r\n<figcaption>Pantalla de juego de Darts<\/figcaption>\r\n<\/figure>\r\n<\/div>\r\n\r\n\r\n\r\n<p>\u00a0<\/p>\r\n\r\n\r\n\r\n<p>\u00bfQu\u00e9 os parece? \u00bfInteresante, verdad?<\/p>\r\n\r\n\r\n\r\n<p>Pues la otra caracter\u00edsticas que hemos usado en el videojuego Darts, es la de agrupaci\u00f3n de Sprites. Ya que nuestra Diana est\u00e1 conformada por la uni\u00f3n de tres de ellos, pero con una ventaja. Una vez unidos, se comportan como uno solo, con lo que los comandos de colisiones, movimientos y posici\u00f3n, los podemos aplicar de manera grupal, con la simplificaci\u00f3n que ello conlleva.<\/p>\r\n\r\n\r\n\r\n<p>Seguro que ya ten\u00e9is ganas de saber mas en profundidad como hemos utilizado todas estas nuevas funciones.<\/p>\r\n\r\n\r\n\r\n<p>\u00a1Pues no esper\u00e9is m\u00e1s, pinchad en el v\u00eddeo de abajo y descubrirlo!<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-embed-youtube aligncenter wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\">\r\n<div class=\"wp-block-embed__wrapper\" style=\"text-align: center\">\r\n<p><iframe loading=\"lazy\" title=\"NextBasic  - Zx Spectrum Next -  Sprites Hardware  - Tutorial 2\" width=\"800\" height=\"450\" src=\"https:\/\/www.youtube.com\/embed\/zFdLiBhdmY4?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen><\/iframe><\/p>\r\n<\/div>\r\n<\/figure>\r\n\r\n\r\n\r\n<p>\u00a0<\/p>\r\n\r\n\r\n\r\n<p>Bueno espero que no os hay\u00e1is perdido el v\u00eddeo, ahora vamos a analizar las caracter\u00edsticas nuevas una por una para que nos queden las cosas un poco m\u00e1s claras y pod\u00e1is avanzar en la Programaci\u00f3n de Videojuegos en Basic para el Zx Spectrum Next<\/p>\r\n\r\n\r\n\r\n<p>Si quer\u00e9is descargados el c\u00f3digo fuente completo, as\u00ed como los Sprites, etc\u2026, ya sab\u00e9is que en mi p\u00e1gina de <a href=\"https:\/\/github.com\/Nextric\/Darts\" target=\"_blank\" rel=\"noreferrer noopener\">GitHub<\/a> lo pod\u00e9is descargar todo.<\/p>\r\n\r\n\r\n\r\n<p>El comando para definir que un Sprite se va a mover mediante movimiento predefinido lo podemos ver aqu\u00ed abajo.<\/p>\r\n\r\n\r\n\r\n<pre class=\"wp-block-code\"><code>SPRITE CONTINUE 0, 20 TO 201 STEP dardovel RUN ,128,0 TO 2<\/code><\/pre>\r\n\r\n\r\n\r\n<p>En esta sentencia definimos que el Sprite que hemos llamado 0 en nuestro programa se va a desplazar en el eje X desde la posici\u00f3n 20 hasta la 201 con incrementos definidos en la variable <em>dardovel<\/em>, aqu\u00ed pod\u00edamos haber puesto un n\u00famero simplemente, y despu\u00e9s le indicamos con la sentencia RUN que se va a desplazar inmediatamente. La posici\u00f3n Y la dejamos fija a 128, porque en este caso nos interesa, y luego lo vinculamos a los Sprites reales del 0 hasta el 2.<\/p>\r\n<p>\u00a0<\/p>\r\n\r\n\r\n\r\n<div class=\"wp-block-image\" style=\"text-align: center\">\r\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" class=\"wp-image-100 aligncenter\" src=\"http:\/\/lacavernainformatica.com\/wp-content\/uploads\/AnimacionDardos.png\" alt=\"\" \/>\r\n<figcaption>Los tres Sprites nos permiten realizar la animaci\u00f3n del Dardo en vuelo<br \/><br \/><\/figcaption>\r\n<\/figure>\r\n<\/div>\r\n\r\n\r\n\r\n<p>Esto \u00faltimo har\u00e1 que en cada iteraci\u00f3n vaya mostrando un Sprite distinto, en este caso para simular el vuelo del dardo.<\/p>\r\n\r\n\r\n\r\n<p>Hay otra puntualizaci\u00f3n que hacer sobre el tema del uso de movimientos autom\u00e1ticos. Necesitamos usar una sentencia para indicarle al Next cuando realizar dicho movimiento.<\/p>\r\n\r\n\r\n\r\n<p>\u00bfY dir\u00e9is, y eso para qu\u00e9? Bueno, supongamos que tenemos varios Sprites definidos con movimientos autom\u00e1ticos, como es el caso de Darts, es necesario que se muevan de una manera controlada por nosotros para que todos vayan a la par. Si arrancara nada m\u00e1s definirlo, ser\u00eda un l\u00edo controlar la sincronizaci\u00f3n de todos, cada uno ir\u00eda a su bola, jajajaja.<\/p>\r\n\r\n\r\n\r\n<p>Bueno el comando que nos permite realizar esto es:<\/p>\r\n\r\n\r\n\r\n<pre class=\"wp-block-code\"><code>550 REM damos la orden de moverse a los sprites de tipo automatico\r\n560 SPRITE MOVE<\/code><\/pre>\r\n\r\n\r\n\r\n<p>\u00bfTodo claro, verdad?<\/p>\r\n\r\n\r\n\r\n<p>Pues ahora trataremos los Sprites agrupados. Como hemos dicho, podemos agrupar varios Sprites, haciendo de uno el principal y de los otros sus esclavos (Esta palabra se quiere eliminar de la inform\u00e1tica por sus connotaciones\u2026)<\/p>\r\n\r\n\r\n\r\n<p>Para ello veamos primero los Sprites que vamos a unir.<\/p>\r\n<p>\u00a0<\/p>\r\n\r\n\r\n\r\n<div class=\"wp-block-image\" style=\"text-align: center\">\r\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" class=\"wp-image-103 aligncenter\" src=\"http:\/\/lacavernainformatica.com\/wp-content\/uploads\/SpritesDiana.png\" alt=\"\" \/>\r\n<figcaption>Sprites que conforman la Diana<br \/><br \/><\/figcaption>\r\n<\/figure>\r\n<\/div>\r\n\r\n\r\n\r\n<p>Nosotros hemos elegido como padre, el Sprite superior y los restantes como su hijos. Para ello tan solo hemos necesitado usar la siguiente sentencia:<\/p>\r\n\r\n\r\n\r\n<pre class=\"wp-block-code\"><code>350 REM agrupacion de sprites. Refenciamos al sprite 3, el 4 y el 5, haciendo uso del -, y de esta forma todo se agrupa al nivel del 3\r\n360 SPRITE 3,200,0,3,1\r\n370 SPRITE -4,,+16,4,1\r\n380 SPRITE -5,,+32,5,1<\/code><\/pre>\r\n\r\n\r\n\r\n<p>Como veis, al usar signos negativos le indicamos al Next que el Sprite 4 y 5, que en este caso los llamamos igual que los Sprites reales de la memoria, son los esclavos del Sprite 3.<\/p>\r\n\r\n\r\n\r\n<p>De esta forma, cuando realizamos el movimiento automatizado, hacemos solo referencia ya al tercer Sprite.<\/p>\r\n\r\n\r\n\r\n<pre class=\"wp-block-code\"><code>510 REM movemos automaticaente la agrupacion de sprites de la diana referenciando unicamente al sprite 3\r\n520 SPRITE CONTINUE 3,200,0 TO 200 STEP dianavel RUN ,3<\/code><\/pre>\r\n\r\n\r\n\r\n<p>Y adem\u00e1s, cuando realizamos el control de colisiones entre la diana y el dardo, cosa que todav\u00eda no hab\u00edamos explicado, lo hacemos solo referenciando al Sprite 3.<\/p>\r\n\r\n\r\n\r\n<p>Veamos como podemos revisar las colisiones entre los distintos Sprites con el siguiente c\u00f3digo:<\/p>\r\n\r\n\r\n\r\n<pre class=\"wp-block-code\"><code>530 REM aqui usamos la gestion de colisiones entre el dardo y el grupo de sprite de la diana. Tambien nos quedamos con la posicion de colision en la diana para calcular los puntos que hay que asignar\r\n540 LET col= % SPRITE OVER (0,3,4,4): IF col > 0 THEN LET pos=% SPRITE AT (3,1): GO SUB %680: SPRITE CONTINUE 0, STOP : GO TO %210<\/code><\/pre>\r\n\r\n\r\n\r\n<p>Y el comando en cuesti\u00f3n que nos interesa:<\/p>\r\n\r\n\r\n\r\n<pre class=\"wp-block-code\"><code>% SPRITE OVER (0,3,4,4)<\/code><\/pre>\r\n\r\n\r\n\r\n<p>En este caso estamos diciendo, que revise la colisi\u00f3n entre el Sprite 0, nuestro dardo, y \u00fanicamente el Sprite 3, pero al estar agrupados, si el dardo colisiona con cualquiera de los otros dos tambi\u00e9n nos devolver\u00e1 que ha colisionado. Los otros n\u00fameros indican el <em>Offset<\/em> que tiene que tener en cuenta para detectar la colisi\u00f3n.<\/p>\r\n\r\n\r\n\r\n<p>No quiero liar mucho la cosa, as\u00ed que pensar que el <em>Offset<\/em> nos permite reducir el \u00e1rea que se debe de tener en cuenta para que una colisi\u00f3n se produzca.<\/p>\r\n<p>\u00a0<\/p>\r\n\r\n\r\n\r\n<div class=\"wp-block-image\" style=\"text-align: center\">\r\n<figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-105 aligncenter\" src=\"http:\/\/lacavernainformatica.com\/wp-content\/uploads\/dardo.png\" alt=\"\" width=\"229\" height=\"230\" \/>\r\n<figcaption>Los Sprites que usamos son de 16\u00d716 pixeles<br \/><br \/><\/figcaption>\r\n<\/figure>\r\n<\/div>\r\n\r\n\r\n\r\n<p>Los Sprites que estamos usando son de 16X16 pixeles, y como veis el dardo, que est\u00e1 centrado aprop\u00f3sito, es bastante m\u00e1s peque\u00f1o. Mediante el <em>Offset<\/em>, simplemente le decimos que reduzca en 4 pixeles tanto de ancho como de alto la detecci\u00f3n para una colisi\u00f3n, por lo que la parte en blanco del Sprite del dardo no ser\u00e1 efectiva para dicho c\u00e1lculo.<\/p>\r\n\r\n\r\n\r\n<p>\u00a0<\/p>\r\n\r\n\r\n\r\n<p>Por \u00faltimo, tan solo nos queda prestar atenci\u00f3n al comando que nos permite conocer la posici\u00f3n de un Spite en particular, con respecto al eje de coordenadas.<\/p>\r\n\r\n\r\n\r\n<pre class=\"wp-block-code\"><code>% SPRITE AT (3,1)<\/code><\/pre>\r\n\r\n\r\n\r\n<p>Aqu\u00ed le indicamos que nos calcule la posici\u00f3n del Sprite 3, recordar que la diana estaba agrupada, en el eje Y. Si quisi\u00e9ramos consultar el eje X, usar\u00edamos un 0 en vez del 1 del comando. Aqu\u00ed solo hacer una aclaraci\u00f3n, sobre todo con respecto al juego Darts.<\/p>\r\n\r\n\r\n\r\n<p>El c\u00e1lculo de posiciones no atiende a las agrupaciones, cosa por otro lado coherente, de manera que en este caso, cuando el dardo colisiona con la diana y le preguntamos que en que posici\u00f3n estaba dicha diana, para poder calcular cuantos puntos ha obtenido el jugador, tendremos que hacer nosotros mismos la extrapolaci\u00f3n de posiciones.<\/p>\r\n\r\n\r\n\r\n<p>\u00bfQu\u00e9 est\u00e1 diciendo este tio?<\/p>\r\n\r\n\r\n\r\n<p>Que s\u00ed, que es m\u00e1s sencillo de lo que parece. Nosotros podemos saber contra que Sprite ha colisionado realmente, si el 3, el 4 o el 5 realizando ciertos c\u00e1lculos. Por un lado sabemos que nuestro dardo se ha lanzado desde la coordenada fija en el eje <em>y<\/em> de 128.<\/p>\r\n<p>\u00a0<\/p>\r\n\r\n\r\n\r\n<div class=\"wp-block-image\">\r\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" class=\"wp-image-181 aligncenter\" src=\"http:\/\/lacavernainformatica.com\/wp-content\/uploads\/AgrupacionDiana.png\" alt=\"\" \/><\/figure>\r\n<\/div>\r\n\r\n\r\n\r\n<p>\u00a0<\/p>\r\n<p>En este caso sabemos que ha colisionado con el sprite 4, porque al pedir la posici\u00f3n de colisi\u00f3n, nos devuelve que ha colisionado por encima de los 128 de la trayectoria del dardo.<\/p>\r\n\r\n\r\n\r\n<p>Para realizar el ajuste fino y poder obtener las distintas puntuaciones de la diana, sabiendo que cada sprite es de 16\u00d716 p\u00edxeles, podemos ir acotando para saber en que zona ha colisionado.<\/p>\r\n\r\n\r\n\r\n<p>Por ejemplo, si el dardo hubiera colisionado con el borde inferior de la diana, sabemos que debe de estar casi 48 pixeles por encima del 128 de referencia. Ser\u00edan unos 16 del Sprite 3 m\u00e1s 16 del Sprite 4 y un aproximadamente otros 16 del Sprite 5. Evidentemente habr\u00eda que detectar un intervalo entre 48 y 46 para detectar el borde rojo de la diana.<\/p>\r\n\r\n\r\n\r\n<p>Bueno no quer\u00eda liaros mucho con la problem\u00e1tica de este c\u00e1lculo pero nos viene bien para ir d\u00e1ndole al coco.<\/p>\r\n\r\n\r\n\r\n<p>En fin, pues hasta aqu\u00ed ha llegado esta entrada, espero que os haya resultado amena y divertida y que os permita seguir avanzando en vuestros desarrollos de Programaci\u00f3n de Videojuegos en Basic para el Zx Spectrum Next.<\/p>\r\n\r\n\r\n\r\n<div class=\"wp-block-image\">\r\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" class=\"wp-image-110 aligncenter\" src=\"http:\/\/lacavernainformatica.com\/wp-content\/uploads\/GameOver_Darts.png\" alt=\"\" \/><\/figure>\r\n<\/div>\r\n","protected":false},"excerpt":{"rendered":"<p>Este es un extracto del art\u00edculo originariamente publicado en mi web lacavernainformatica.com Bueno seguro que si ya hab\u00e9is visto y practicado con la primera entrega, tendr\u00e9is muchas ganas de seguir avanzando en la Programaci\u00f3n del NextBasic. Y es que todav\u00eda tenemos muchos m\u00e1s comandos y operaciones que podemos realizar sobre nuestros Sprites. Sobre todo en [&hellip;]<\/p>\n","protected":false},"author":14,"featured_media":73,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[3,4],"tags":[6],"class_list":["post-46","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-desarrollo","category-nextbasic","tag-nextbasic"],"jetpack_featured_media_url":"https:\/\/specnext.dev\/es\/wp-content\/uploads\/sites\/2\/2020\/11\/DestacadaTutorial2.png","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/specnext.dev\/es\/wp-json\/wp\/v2\/posts\/46","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/specnext.dev\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/specnext.dev\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/specnext.dev\/es\/wp-json\/wp\/v2\/users\/14"}],"replies":[{"embeddable":true,"href":"https:\/\/specnext.dev\/es\/wp-json\/wp\/v2\/comments?post=46"}],"version-history":[{"count":6,"href":"https:\/\/specnext.dev\/es\/wp-json\/wp\/v2\/posts\/46\/revisions"}],"predecessor-version":[{"id":110,"href":"https:\/\/specnext.dev\/es\/wp-json\/wp\/v2\/posts\/46\/revisions\/110"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/specnext.dev\/es\/wp-json\/wp\/v2\/media\/73"}],"wp:attachment":[{"href":"https:\/\/specnext.dev\/es\/wp-json\/wp\/v2\/media?parent=46"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/specnext.dev\/es\/wp-json\/wp\/v2\/categories?post=46"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/specnext.dev\/es\/wp-json\/wp\/v2\/tags?post=46"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}