tag:blogger.com,1999:blog-20997666540993114672024-03-19T08:58:12.554+01:00Imanolea's GamesBlog de seguimiento de los desarrollos en los que participa Imanol Barriuso.Imanoleahttp://www.blogger.com/profile/03989722316939496203noreply@blogger.comBlogger66125tag:blogger.com,1999:blog-2099766654099311467.post-11132900012683320492018-01-29T23:40:00.002+01:002018-01-30T12:26:07.562+01:00Spread It Out (Global Game Jam 2018)Videojuego realizado en 48 horas para la <a href="https://twitter.com/gamejamon">Game Jam On 2018</a> (Global Game Jam) por <a href="https://twitter.com/Imanolea">Imanol Barriuso</a>, <a href="https://twitter.com/Pelayo3D">Pelayo Martinez</a> y <a href="https://twitter.com/fer_kaos_olea">Fernando Olea</a>.<br />
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
<iframe allow="autoplay; encrypted-media" allowfullscreen="" frameborder="0" height="289" src="https://www.youtube.com/embed/BHLYrTCbU78" width="510"></iframe>
</div>
<br />
<b>Plataforma:</b> Oculus Rift<br />
<b>Página del juego:</b> <a href="https://globalgamejam.org/2018/games/spread-it-out">https://globalgamejam.org/2018/games/spread-it-out</a><br />
<br />Imanoleahttp://www.blogger.com/profile/03989722316939496203noreply@blogger.com0tag:blogger.com,1999:blog-2099766654099311467.post-79216344188126369462017-12-27T12:14:00.002+01:002019-07-30T13:48:25.816+02:00Last Crown Warriors #3: Collisions<div style="text-align: justify;">
<span class="" id="result_box" lang="en"><span class="">The Last Crown Warriors <a href="https://lightgamesgb.com/portfolio/last-crown-warriors/">DEMO</a> has been published recently.</span> <span class="">Since
the last entry on Imanolea's Games about the game has been some
time, and much functionality is pending for explanation.</span> <span class="">So I decided to ask on Twitter for the feature or system of Last Crown Warriors that you would like to be clarified on the blog.</span></span></div>
<div style="text-align: justify;">
<blockquote class="twitter-tweet" data-lang="es">
<div dir="ltr" lang="en">
Now that the demo of <a href="https://twitter.com/hashtag/LastCrownWarriors?src=hash&ref_src=twsrc%5Etfw">#LastCrownWarriors</a> has been published, I will write about how some of its features have been programmed on Imanolea's Games. Is there one that interests you in particular?<a href="https://twitter.com/hashtag/gameboy?src=hash&ref_src=twsrc%5Etfw">#gameboy</a> <a href="https://twitter.com/hashtag/gamedev?src=hash&ref_src=twsrc%5Etfw">#gamedev</a> <a href="https://twitter.com/hashtag/indiedev?src=hash&ref_src=twsrc%5Etfw">#indiedev</a></div>
— Imanol Barriuso (@Imanolea) <a href="https://twitter.com/Imanolea/status/938418270675374085?ref_src=twsrc%5Etfw">6 de diciembre de 2017</a></blockquote>
<script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script>
</div>
<div style="text-align: justify;">
<span class="" id="result_box" lang="en"><span class="">From this announce I received an email from Jonas proposing to write about the collisions.</span></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<div id="gt-res-content">
<div class="trans-verified-button-small" dir="ltr" id="gt-res-dir-ctr">
<span class="" id="result_box" lang="en">It is not the first time that I perceive interest in reading an entry dedicated to collisions. It </span><span class="" id="result_box" lang="en"><span class="short_text" id="result_box" lang="en"><span class="">is something present in almost any type of game</span></span>, but a lot </span><span class="" id="result_box" lang="en"><span class="" id="result_box" lang="en">has been written about it</span>. <span class="">So I did not have the impression that I could offer something interesting on the subject.</span></span></div>
</div>
</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span class="" id="result_box" lang="en">Now, it is also true that this routine sometimes involves </span><span class="" id="result_box" lang="en"><span class="short_text" id="result_box" lang="en"><span class="">a lot of processing </span></span></span><span class="" id="result_box" lang="en"><span class="short_text" id="result_box" lang="en"><span class=""><span class="short_text" id="result_box" lang="en"><span class="">in each of the frames</span></span></span></span>. <span class="">And
just as in the times of the classic microcomputers a good scroll routine could
make your game stand out from the others, a good collision processing
can allow you (also nowadays) to maximize the number of enemies,
projectiles, power ups,</span> <span class="">and other interactive objects that we see on the screen.</span></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span class="" id="result_box" lang="en"><span class="">And
naturally, managing a pixel-level collision in a modern video game
engine is not the same as trying to set up the collision of multiple
elements in a system like the Game Boy.</span> <span class="">So in the end I found that it could be interesting to show the way in which I try to face this challenge.</span> My <span class="">system is far from being the best, but I think it can inspire others to try to work on their own approach.</span></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span class="" id="result_box" lang="en"><span class="">In Last Crown Warriors it is necessary to manage collisions in the following list of situations:</span></span></div>
<ul style="text-align: justify;">
<li><span class="short_text" id="result_box" lang="en"><span class="">Collision of the hero with background</span></span></li>
<li>Collision of the enemies with the background </li>
<li>Collision of the hero's weapon with the enemies</li>
<li>Collision of the hero's special weapon with the enemies</li>
<li>Collision of the hero with the enemies</li>
<li>Collision of the hero with interactive elements (such as the health heart)</li>
</ul>
<div style="text-align: justify;">
<span class="" id="result_box" lang="en"><span class="">All these collisions occur simultaneously, and it is crucial to minimize slowdowns as much as possible.</span> <span class="">So the routines must be extremely efficient.</span></span></div>
<br />
<div style="text-align: justify;">
<span class="" id="result_box" lang="en"><span class="">The collisions
previously enumerated are essentially managed through two systems, which
I will explain throughout this entry.</span></span></div>
<ol style="text-align: justify;">
<li>Collision of a character with another character</li>
<li>Collision of a character with the background</li>
</ol>
<div style="text-align: justify;">
<span class="" id="result_box" lang="en"><span class="">And although they both manage collisions they have a completely different approach, as you will see below.</span></span><br />
<br />
<div id="gt-res-content">
<div class="trans-verified-button-small" dir="ltr" id="gt-res-dir-ctr">
<span class="" id="result_box" lang="en">As always, I will try to focus on explaining the logical concepts behind the systems. <span class="">So that they can be understood and applied without having to go through lines of code.</span></span></div>
</div>
<br /></div>
<div style="text-align: justify;">
</div>
<h4 style="text-align: justify;">
Collision of a character with another character</h4>
<h4>
</h4>
<div style="text-align: justify;">
<span class="" id="result_box" lang="en"><span class="">Let's take as an example the collision of the hero with the enemies for this routine.</span> <span class="">Let's see, to be able to verify if the hero has collided with an specific enemy we would have the following data:</span></span></div>
<ol style="text-align: justify;">
<li>X and Y coordinate of the hero</li>
<li>X and Y coordinate of the enemy</li>
<li>Width and height of the collision area of the hero</li>
<li>Width and height of the collision area of the enemy</li>
</ol>
<div style="text-align: justify;">
<span class="" id="result_box" lang="en"><span class="">With this information we could shape two areas (the hero's and the enemy's), and check if those two areas overlap.</span> <span class="">And while it would be a valid solution, it is not by far an acceptable solution.</span> Because although the area of the hero would only be calculated at the beginning
of the routine, the enemy area should be recalculated by each of the
enemy characters.</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span class="" id="result_box" lang="en">And what can we do? <span class="">Let's
see, we know that all enemies share the same size collision area, so
why not generate a single area around the hero that combines the area
lengths of both characters?</span> <span class="">That is, instead of
checking if two areas overlap, check if the enemy coordinate is within
the combined collision area of the hero.</span></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEht2mDa9PMI5MZKPof9ItsQYmqYhlH58B80Ill_rXu58A8fuznlFY7yPqzSYRtmVHzUu3oKR1cd8QWKVTcUabYn4bPwvpimARnLcJdUG6L8BkgpyMnGDF2VMbk30mX79GEDiC9IBro7NDc/s1600/collision_areas_big.png" imageanchor="1"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEht2mDa9PMI5MZKPof9ItsQYmqYhlH58B80Ill_rXu58A8fuznlFY7yPqzSYRtmVHzUu3oKR1cd8QWKVTcUabYn4bPwvpimARnLcJdUG6L8BkgpyMnGDF2VMbk30mX79GEDiC9IBro7NDc/s400/collision_areas_big.png" width="400" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">Purple: Point of character position.</span><br />
<span style="font-size: x-small;">Orange: Character collision area.</span><br />
<span style="font-size: x-small;">Blue: Combined collision area of the hero.</span></div>
<div style="text-align: center;">
<br />
<div style="text-align: justify;">
So we would only have to calculate the blue area of the image by adding the dimensions of the collision area of the hero and the enemy's. And once we have it, and with a maximum of four simple comparisons, we check if the enemy's position point is within that area. In this way we minimize the processing to be performed by each of the additional enemies with which we want to check if our hero has collided.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
This code shows the core of the check between the enemy character's position point and the combined collision area.</div>
<div style="text-align: justify;">
<br /></div>
<script src="https://pastebin.com/embed_js/EvUZLnTF"></script>
<br />
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
We can see how this routine returns the address in memory of the enemy that we have just checked. So we could place it without problems inside a loop that goes through the list of enemies on which we want to perform the collision check.<br />
<br />
<h4>
Collision of a character with the background</h4>
In this case we will always go through the same routine when checking this type of collision. Since only the hero and the enemies can collide with the background, and both share the same dimensions in the collision area.<br />
<br />
The data to keep in mind for this routine is:<br />
<ol>
<li>X and Y coordinate of the character</li>
<li>Horizontal and vertical movement of the character</li>
<li>X and Y position of the background</li>
<li>Width and height of the map</li>
</ol>
The first thing would be to get the absolute coordinates of the character, that is, the coordinates of the character within the map. For this we add the position of the background to the coordinate of the character.<br />
<br />
Then we need to know the candidate position point to collide. For this we take into account the movement of the character, and we obtain the position of the edge of the collision area closest to colliding. If the character is not moving, we would automatically conclude that he has not collided.<br />
<br />
Once we have the candidate position, it is important to check its relative position within the tile. I mean, if the character is aligned with the tile grid (and taking into account its collision area) we will only check the collision of a single tile, while in the rest of the cases it will be necessary to go through more than one tile.<br />
<br />
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimfQGnIsIDtmjL5oGcQihl7tcc9aSVRK-Nn3Hr6CJJj839tOY9H0vW7sDcIEvAafDIMSnxJRmYSrDKtM77CMHoJlDDz_FVXzvAXZCG-4ydTfHzKAtM32OTKjUGjbf1hkEiduKUlLtKdMo/s1600/map_ss_areas.png" imageanchor="1"><img border="0" height="398" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimfQGnIsIDtmjL5oGcQihl7tcc9aSVRK-Nn3Hr6CJJj839tOY9H0vW7sDcIEvAafDIMSnxJRmYSrDKtM77CMHoJlDDz_FVXzvAXZCG-4ydTfHzKAtM32OTKjUGjbf1hkEiduKUlLtKdMo/s400/map_ss_areas.png" width="400" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">Purple: Collision candidate position point</span><br />
<span style="font-size: x-small;">Orange: Character collision area</span><br />
<span style="font-size: x-small;">Blue: Collisionable Tiles</span><br />
<span style="font-size: x-small;">Red: Solid tiles </span></div>
<div style="text-align: left;">
</div>
<br />
Once we have clear the absolute positions of the tiles we must place them within the map, this is where the width and height of our map come into play.<br />
<br />
And after having obtained the value relative to the collisionable tiles, how do we know if these are solid or not? Very simple, for each map we organize the tileset so that the solid tiles are at the end of the list and the non-solid ones at the beginning. Then we have only to specify what will be the position of the list from which the tile will be considered solid.<br />
<br />
<br />
And this would be the explanation of how Last Crown Warriors collisions work. I hope that it has been interesting and has helped you to understand how a collision system can be set up in a limited hardware.<br />
<br />
If you want to know how a particular aspect of the game works, tell me about it and I will try to talk about it in future posts.</div>
<div style="text-align: justify;">
<br /></div>
</div>
<div style="text-align: center;">
</div>
Imanoleahttp://www.blogger.com/profile/03989722316939496203noreply@blogger.com0tag:blogger.com,1999:blog-2099766654099311467.post-78589568515432862992017-12-27T12:14:00.001+01:002019-01-30T13:13:21.247+01:00Last Crown Warriors #3: Colisiones<div style="text-align: justify;">
La <a href="https://lightgamesgb.com/portfolio/last-crown-warriors/">DEMO</a> de Last Crown Warriors ha sido publicada recientemente. Desde la última entrada de Imanolea's Games dedicada al juego ha pasado algún tiempo, y mucha funcionalidad ha quedado pendiente de ser explicada. Así que decidí preguntar por Twitter por la característica o sistema de Last Crown Warriors que os gustaría que fuera destripado en el blog.</div>
<div style="text-align: justify;">
<blockquote class="twitter-tweet" data-lang="es">
<div dir="ltr" lang="en">
Now that the demo of <a href="https://twitter.com/hashtag/LastCrownWarriors?src=hash&ref_src=twsrc%5Etfw">#LastCrownWarriors</a> has been published, I will write about how some of its features have been programmed on Imanolea's Games. Is there one that interests you in particular?<a href="https://twitter.com/hashtag/gameboy?src=hash&ref_src=twsrc%5Etfw">#gameboy</a> <a href="https://twitter.com/hashtag/gamedev?src=hash&ref_src=twsrc%5Etfw">#gamedev</a> <a href="https://twitter.com/hashtag/indiedev?src=hash&ref_src=twsrc%5Etfw">#indiedev</a></div>
— Imanol Barriuso (@Imanolea) <a href="https://twitter.com/Imanolea/status/938418270675374085?ref_src=twsrc%5Etfw">6 de diciembre de 2017</a></blockquote>
<script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script>
</div>
<div style="text-align: justify;">
En base a este anuncio recibí un mail del compañero Jonas proponiendo escribir sobre las colisiones.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
No es la primera vez que percibo interés por ver una entrada dedicada a las colisiones. Es algo con lo que tenemos que lidiar en casi cualquier tipo de juego, pero también algo sobre lo que se ha escrito mucho. Así que no me pareció un tema sobre el cual yo pudiera ofrecer algo interesante.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Ahora bien, también es cierto que esta rutina engloba en ocasiones gran parte del procesamiento de cada uno de los frames. Y al igual que en la época de los microordenadores una buena rutina de scroll podía hacer destacar tu juego de entre los demás, un buen procesamiento de colisiones puede permitirte (también a día de hoy) maximizar el número de enemigos, proyectiles, power ups, y demás objetos interactuables que vemos en pantalla.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Y naturalmente, no es lo mismo gestionar una colisión a nivel de píxel en un motor de videojuegos moderno que intentar plantear la colisión de multiples elementos en un sistema como el de la Game Boy. Así que en última instancia me pareció interesante mostrar la manera en la que yo procuro enfrentar este reto. Que si bien se encuentra lejos de ser la mejor, creo que puede inspirar a otros a probar suerte con su propio enfoque.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Concretamente en Last Crown Warriors vemos necesario gestionar colisiones en la siguiente lista de situaciones:</div>
<ul style="text-align: justify;">
<li>Colisión de héroe con fondo</li>
<li>Colisión de los enemigos con el fondo </li>
<li>Colisión del arma del héroe con los enemigos</li>
<li>Colisión del arma especial del héroe con los enemigos</li>
<li>Colisión del héroe con los enemigos</li>
<li>Colisión del héroe con elementos interactuables (como el corazón de salud)</li>
</ul>
<div style="text-align: justify;">
Todas estas colisiones se producen simultáneamente, y es crucial minimizar en la medida de lo posible las ralentizaciones. Por lo que las rutinas deben ser extremadamente eficientes.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Las colisiones previamente enumeradas se gestionan en esencia a través de dos sistemas, que son los que explicaré a lo largo de esta entrada.</div>
<ol style="text-align: justify;">
<li>Colisión de personaje con personaje</li>
<li>Colisión de personaje con fondo</li>
</ol>
<div style="text-align: justify;">
Y aunque los dos gestionen colisiones tienen un planteamiento completamente distinto, tal y como veréis a continuación.<br />
<br />
Como siempre, procuraré centrarme en explicar los conceptos lógicos detrás de los sistemas. De manera que se puedan entender y aplicar sin necesidad de recorrer líneas de código.<br />
<br /></div>
<div style="text-align: justify;">
</div>
<h4 style="text-align: justify;">
Colisión de personaje con personaje</h4>
<h4>
</h4>
<div style="text-align: justify;">
Vamos a tomar como ejemplo la colisión del héroe con los enemigos para esta rutina. Veamos, para poder comprobar si el héroe ha colisionado con un enemigo concreto dispondríamos de los siguientes datos:</div>
<ol style="text-align: justify;">
<li>Coordenada X e Y del héroe</li>
<li>Coordenada X e Y del enemigo</li>
<li>Ancho y alto del área de colisión del héroe</li>
<li>Ancho y alto del área de colisión del enemigo</li>
</ol>
<div style="text-align: justify;">
Con esta información podríamos conformar dos áreas (la del héroe y la del enemigo), y comprobar si esas dos áreas se superponen. Y si bien sería una solución válida, no es ni de lejos una solución aceptable. Ya que aunque el área del héroe sólo la calcularíamos al principio de la rutina, el área enemiga debería recalcularse por cada uno de los personajes enemigos.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
¿Y qué podemos hacer? A ver, sabemos que todos los enemigos comparten el mismo tamaño de área de colisión, así que, ¿por qué no generar una única área alrededor del héroe que combine las longitudes de área de ambos personajes? Es decir, en lugar de comprobar si dos áreas se superponen, comprobar si la coordenada enemiga se encuentra dentro del área de colisión combinada del héroe.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEht2mDa9PMI5MZKPof9ItsQYmqYhlH58B80Ill_rXu58A8fuznlFY7yPqzSYRtmVHzUu3oKR1cd8QWKVTcUabYn4bPwvpimARnLcJdUG6L8BkgpyMnGDF2VMbk30mX79GEDiC9IBro7NDc/s1600/collision_areas_big.png" imageanchor="1"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEht2mDa9PMI5MZKPof9ItsQYmqYhlH58B80Ill_rXu58A8fuznlFY7yPqzSYRtmVHzUu3oKR1cd8QWKVTcUabYn4bPwvpimARnLcJdUG6L8BkgpyMnGDF2VMbk30mX79GEDiC9IBro7NDc/s400/collision_areas_big.png" width="400" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">Morado: Punto de posición de personaje.</span></div>
<div style="text-align: center;">
<span style="font-size: x-small;">Naranja: Área de colisión de personaje.</span></div>
<div style="text-align: center;">
<span style="font-size: x-small;">Azul: Área de colisión combinada del héroe.</span><br />
<br />
<div style="text-align: justify;">
Así sólo tendríamos que calcular el área azul de la imagen sumando las dimensiones del área de colisión del héroe y de un enemigo. Y una vez la tengamos, y con un máximo de cuatro comparaciones simples, comprobamos si el punto de posición del enemigo se encuentra dentro de dicha área. De esta forma minimizamos el procesamiento a realizar por cada uno de los enemigos adicionales con los que queramos comprobar si ha colisionado nuestro héroe.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Este extracto de código muestra el núcleo de la comprobación entre el punto de posición del personaje enemigo y el área de colisión combinada.</div>
<div style="text-align: justify;">
<br /></div>
<script src="https://pastebin.com/embed_js/tZkCLGMS"></script>
<br />
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Podemos ver como esta rutina nos devuelve la dirección en memoria del enemigo sobre el que acabamos de realizar la comprobación. Así que podríamos ubicarla sin problemas dentro de un bucle que recorra la lista de enemigos sobre los que queremos realizar la comprobación de colisión.<br />
<br />
<h4>
Colisión de personaje con fondo </h4>
En este caso pasaremos siempre por la misma rutina a la hora de comprobar este tipo de colisión. Ya que únicamente el héroe y los enemigos pueden colisionar con el fondo, y ambos comparten las mismas dimensiones en el área de colisión. <br />
<br />
Los datos a tener en cuenta para esta rutina son:<br />
<ol>
<li>Coordenada X e Y del personaje</li>
<li>Desplazamiento horizontal y vertical del personaje</li>
<li>Posición X e Y del fondo</li>
<li>Ancho y alto del mapa</li>
</ol>
Lo primero sería conseguir las coordenadas absolutas del personaje, es decir, las coordenadas del personaje dentro del mapa. Para ello sumamos la posición del fondo a la coordenada del personaje.<br />
<br />
Luego necesitamos saber el punto de posición candidato a colisionar. Para ello tenemos en cuenta el desplazamiento del personaje, y obtenemos la posición del extremo del área de colisión más próximo a colisionar. Si el personaje no se está desplazando, interpretaríamos automáticamente que no ha colisionado. <br />
<br />
Una vez tenemos la posición candidata, es importante comprobar qué posición relativa ocupa dentro del tile. Me explico, si el personaje se encuentra alineado con la rejilla de tiles (y teniendo en cuenta su área de colisión) verificaremos únicamente la colisión de un tile, mientras que en el resto de casos será necesario pasar por más de uno.<br />
<br />
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimfQGnIsIDtmjL5oGcQihl7tcc9aSVRK-Nn3Hr6CJJj839tOY9H0vW7sDcIEvAafDIMSnxJRmYSrDKtM77CMHoJlDDz_FVXzvAXZCG-4ydTfHzKAtM32OTKjUGjbf1hkEiduKUlLtKdMo/s1600/map_ss_areas.png" imageanchor="1"><img border="0" height="398" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimfQGnIsIDtmjL5oGcQihl7tcc9aSVRK-Nn3Hr6CJJj839tOY9H0vW7sDcIEvAafDIMSnxJRmYSrDKtM77CMHoJlDDz_FVXzvAXZCG-4ydTfHzKAtM32OTKjUGjbf1hkEiduKUlLtKdMo/s400/map_ss_areas.png" width="400" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">Morado: Punto de posición candidato a colisión</span></div>
<div style="text-align: center;">
<span style="font-size: x-small;">Naranja: Aréa de colisión del personaje</span></div>
<div style="text-align: center;">
<span style="font-size: x-small;">Azul: Tiles colisionables</span></div>
<div style="text-align: center;">
<span style="font-size: x-small;">Rojo: Tiles sólidos </span></div>
<div style="text-align: left;">
</div>
<br />
Pues una vez tenemos claras las posiciones absolutas de los tiles debemos ubicarlas dentro del mapa, aquí es donde entra en juego el ancho y el alto de nuestro mapeado.<br />
<br />
Y tras haber obtenido el valor relativo a los tiles colisionables, ¿cómo sabemos si estos son sólidos o no? Muy sencillo, para cada mapa organizamos el tileset de manera que los tiles sólidos quedan al final de la lista y los no sólidos al principio. Luego no tenemos más que especificar cuál será la posición de la lista a partir del cuál se considerará que el tile es solido.<br />
<br />
<br />
Hasta aquí la explicación de cómo funcionan las colisiones de Last Crown Warriors. Espero que os haya resultado interesante y os haya servido para entender cómo se puede plantear un sistema de colisiones en un hardware como el de la Game Boy.<br />
<br />
Si queréis saber cómo funciona algún aspecto concreto de juego, comentádmelo e intentaré hablar sobre él en próximas entradas.</div>
<div style="text-align: justify;">
<br /></div>
</div>
<div style="text-align: center;">
</div>
Imanoleahttp://www.blogger.com/profile/03989722316939496203noreply@blogger.com1tag:blogger.com,1999:blog-2099766654099311467.post-50489456260047558822017-10-08T23:30:00.004+02:002017-10-09T00:04:55.150+02:00Last Crown Warriors #2: Selection screen<div style="text-align: justify;">
Yesterday <a href="https://twitter.com/lightgamesgb">Light Games</a> published a new development of Last Crown Warriors, in which the character and scenario selection screen was shown.</div>
<blockquote class="twitter-tweet" data-lang="es">
<div dir="ltr" lang="en">
Character and scenario selection screen of <a href="https://twitter.com/hashtag/LastCrownWarriors?src=hash&ref_src=twsrc%5Etfw">#LastCrownWarriors</a>.<a href="https://twitter.com/hashtag/gameboy?src=hash&ref_src=twsrc%5Etfw">#gameboy</a> <a href="https://twitter.com/hashtag/musou?src=hash&ref_src=twsrc%5Etfw">#musou</a> <a href="https://twitter.com/hashtag/pixelart?src=hash&ref_src=twsrc%5Etfw">#pixelart</a> <a href="https://twitter.com/hashtag/gamedev?src=hash&ref_src=twsrc%5Etfw">#gamedev</a> <a href="https://twitter.com/hashtag/screenshotsaturday?src=hash&ref_src=twsrc%5Etfw">#screenshotsaturday</a> <a href="https://twitter.com/hashtag/indiedev?src=hash&ref_src=twsrc%5Etfw">#indiedev</a> <a href="https://t.co/oZb11eSrM5">pic.twitter.com/oZb11eSrM5</a></div>
— Light Games (@lightgamesgb) <a href="https://twitter.com/lightgamesgb/status/916778067409997824?ref_src=twsrc%5Etfw">7 de octubre de 2017</a></blockquote>
<div style="text-align: justify;">
In the video we can see how the movement of two backgrounds occurs simultaneously (the selection bar and the map at the top). And we can also see a non-linear movement, with accelerations and decelerations.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
At logic level, achieving these features in a program should not be a big challenge. Although in the case of the Game Boy, given the limitations of the system, a little prior planning is necessary. So leaving aside the technicalities and focusing on the logical design I'll explain the key elements of this selection screen.</div>
<h4>
</h4>
<h4>
Sinusoidal movement
</h4>
<div style="text-align: justify;">
In order to achieve greater dynamism, it has been decided to apply a sinusoidal movement in the shifts of the bar, the top map, the arrows, and the selectable characters. Calculating the sine of a number would be an overly expensive task for a Game Boy, so a little part of the memory has been sacrificed and these shifts have been stored in data tables.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
By going throught the values of a table like this, we can apply to the elements the proper movement in each iteration. This table represents the top map shift when leaving the screen.</div>
<h4>
<script src="https://pastebin.com/embed_js/T0aC7JHR"></script> </h4>
<h4>
Scene composition</h4>
<div style="text-align: justify;">
The logic of this screen uses some of the properties of the Game Boy system, such as hardware scroll or sprites. In this image the components are differentiated by color.</div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen="" class="giphy-embed" frameborder="0" height="432" src="https://giphy.com/embed/d2jjAxrYmnRWwcJG" width="480"><br></iframe></div>
<br />
<div style="text-align: justify;">
In red: sprites; in blue: the main background; in purple: the secondary background or window.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
As you can see, moving the top scenario is as simple as applying the Game Boy hardware scroll on the main background. Of course, you have to keep in mind that this map must be redrawn. In this case there is only one selectable scenario, but in the case of having more than one, it would be necessary to reprint the background with each selection change. In the following image we see the evolution of the main background during that change.</div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen="" class="giphy-embed" frameborder="0" height="480" src="https://giphy.com/embed/l1J9MmRtvwInbgj5K" width="476"><br></iframe></div>
<br />
<div style="text-align: justify;">
This is the Game Boy main background, the red box being the visible area of the screen during the scenario change. Through one limit of the visible area we first remove the current map and later we print the new one.</div>
<br />
<div style="text-align: justify;">
The window have a disadvantage. It is not possible to reduce its horizontal coordinate below zero, which would be the natural way to make it enter the left limit of the screen. So as you can see, we use an auxiliary sprite during the movement that <span class="short_text" id="result_box" lang="en"><span class="">joins the bar</span></span>.
</div>
<br />
<h4>
Graphical update
</h4>
<div style="text-align: justify;">
In addition to the shifts there are also times when we have to reload the graphics of the backgrounds. The most obvious (and costly) of these reloads is the update of the window once the selection shift ends and all the icons alter their order.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The solution is to have a strict control of the VBlank interruption, and to optimize the graphic reprint. This routine is the responsible for reloading the window, and already has the list of values to copy ready. The formula in this case is the same as the one used in the Last Crown Warriors scroll, which I explain in <a href="https://imanoleasgames.blogspot.com.es/2017/04/last-crown-warriors-1-building-scroll.html">this entry</a>.</div>
<br />
<script src="https://pastebin.com/embed_js/usTvv32x"></script>
<br />
<div style="text-align: justify;">
Now it's time to develop the game system of Last Crown Warriors. Any functionality that deserves to be explained, will be the focus of the next blog entries.</div>
<br />
<script async="" charset="utf-8" src="//platform.twitter.com/widgets.js"></script>Imanoleahttp://www.blogger.com/profile/03989722316939496203noreply@blogger.com0tag:blogger.com,1999:blog-2099766654099311467.post-82680332507118307152017-10-08T23:30:00.003+02:002017-10-10T09:51:47.090+02:00Last Crown Warriors #2: Pantalla de selección<div style="text-align: justify;">
Ayer mismo publicaba <a href="https://twitter.com/lightgamesgb">Light Games</a> un nuevo avance de Last Crown Warriors en el que se mostraba la pantalla de selección de personaje y escenario.</div>
<blockquote class="twitter-tweet" data-lang="es">
<div dir="ltr" lang="en">
Character and scenario selection screen of <a href="https://twitter.com/hashtag/LastCrownWarriors?src=hash&ref_src=twsrc%5Etfw">#LastCrownWarriors</a>.<a href="https://twitter.com/hashtag/gameboy?src=hash&ref_src=twsrc%5Etfw">#gameboy</a> <a href="https://twitter.com/hashtag/musou?src=hash&ref_src=twsrc%5Etfw">#musou</a> <a href="https://twitter.com/hashtag/pixelart?src=hash&ref_src=twsrc%5Etfw">#pixelart</a> <a href="https://twitter.com/hashtag/gamedev?src=hash&ref_src=twsrc%5Etfw">#gamedev</a> <a href="https://twitter.com/hashtag/screenshotsaturday?src=hash&ref_src=twsrc%5Etfw">#screenshotsaturday</a> <a href="https://twitter.com/hashtag/indiedev?src=hash&ref_src=twsrc%5Etfw">#indiedev</a> <a href="https://t.co/oZb11eSrM5">pic.twitter.com/oZb11eSrM5</a></div>
— Light Games (@lightgamesgb) <a href="https://twitter.com/lightgamesgb/status/916778067409997824?ref_src=twsrc%5Etfw">7 de octubre de 2017</a></blockquote>
<div style="text-align: justify;">
En el vídeo podemos ver cómo se produce el desplazamiento de dos fondos de manera simultánea (el de la barra de selección y el del mapa de la parte superior). Y también se puede apreciar un movimiento no lineal, con aceleraciones y deceleraciones.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
A nivel lógico, conseguir plasmar estas características en un programa no debería suponer un gran reto. Aunque en el caso de la Game Boy, dadas las limitaciones del sistema, se hace necesaria una pequeña planificación previa. Así que dejando a un lado los tecnicismos y centrándome en el diseño lógico, paso a exlicaros las claves funcionales de esta pantalla de selección.</div>
<h4>
</h4>
<h4>
Movimiento sinusoidal
</h4>
<div style="text-align: justify;">
De cara a lograr un mayor dinamismo se ha optado por aplicar un movimiento sinusoidal en los desplazamientos de la barra, del escenario del fondo superior, de las flechas, y de los personajes seleccionables. Calcular el seno de un número sería una tarea excesivamente costosa para una Game Boy, por lo que se ha sacrificado un poco de memoria y se han almacenado estos desplazamientos en tablas de datos.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Así, recorriendo los valores de una tabla como esta, podemos aplicar al elemento el desplazamiento indicado en cada iteración. Esta tabla representa el desplazamiento del mapa superior al abandonar la pantalla.</div>
<h4>
<script src="https://pastebin.com/embed_js/T0aC7JHR"></script> </h4>
<h4>
Composición de la escena </h4>
<div style="text-align: justify;">
La lógica de esta pantalla se sirve de alguna de las propiedades del sistema de la Game Boy, como es el scroll por hardware o los sprites. En esta imagen están diferenciados por color los distintpos componentes en acción.</div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen="" class="giphy-embed" frameborder="0" height="432" src="https://giphy.com/embed/d2jjAxrYmnRWwcJG" width="480"><br></iframe></div>
<br />
<div style="text-align: justify;">
En rojo: sprites; en azul: el fondo principal; en morado: el fondo secundario o ventana.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Como veis, desplazar el escenario de la parte superior es tan sencillo como aplicar el scroll por hardware de Game Boy en el fondo principal. Eso sí, hay que tener en cuenta que dicho mapa debe ser redibujado. Ya que en este caso sólo hay un escenario seleccionable, pero en el caso de haber más sería necesario reimprimir el fondo con cada cambio de selección. En la siguiente imagen vemos la evolución del fondo principal durante dicho cambio.</div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen="" class="giphy-embed" frameborder="0" height="480" src="https://giphy.com/embed/l1J9MmRtvwInbgj5K" width="476"><br></iframe></div>
<br />
<div style="text-align: justify;">
Este es fondo principal de Game Boy, siendo el recuadro rojo la zona visible de la pantalla durante el cambio de escenario. Por un lateral de la zona visible eliminamos primero el mapa actual para más tarde imprimir el nuevo.</div>
<br />
<div style="text-align: justify;">
Y en cuanto a la ventana tenemos una desventaja. No es posible reducir su posición horizontal por debajo de cero, que sería la forma natural de introducirla por el límite izquierdo de la pantalla. Así que como se puede observar, nos servimos de un sprite auxiliar durante el desplazamiento que parece mimetizarse con la barra.
</div>
<br />
<h4>
Actualización gráfica</h4>
<div style="text-align: justify;">
Además de los desplazamientos también hay momentos en los que se deben recargar los gráficos de los fondos. La más evidente (y costosa) de estas recargas es la relativa a la actualización de la ventana una vez el cambio de selección termina, donde todos los iconos que la componen ven alterado su orden.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
La solución pasa por tener un control estricto de la interrupción de VBlank, y en optimizar al máximo la reimpresión gráfica. Esta rutina es la encargada de recargar la ventana, la cual ya cuenta con la lista de valores a copiar. La fórmula en este caso respecto a la actualización gráfica es la misma que la usada en el scroll de Last Crown Warriors, la cual explico en <a href="https://imanoleasgames.blogspot.com.es/2017/04/last-crown-warriors-1-creando-el.html">esta entrada</a>.</div>
<br />
<script src="https://pastebin.com/embed_js/usTvv32x"></script>
<br />
<div style="text-align: justify;">
A partir de ahora toca empezar a desarrollar y profundizar en el sistema de juego de Last Crown Warriors. Cualquier funcionalidad que merezca ser explicada, será protagonista de las próximas entradas.</div>
<br />
<script async="" charset="utf-8" src="//platform.twitter.com/widgets.js"></script>
Imanoleahttp://www.blogger.com/profile/03989722316939496203noreply@blogger.com2tag:blogger.com,1999:blog-2099766654099311467.post-68730198440701109792017-07-07T19:01:00.002+02:002017-07-07T19:17:05.703+02:00Sheep Kaboom (BitBitJam4)Game Boy game made during a week by Light Games for <a href="http://jams.gamejolt.io/bitbitjam4">#BitBitJam4</a><br />
<br />
<i>Hold A to charge the shoot. Release it to launch the sheep.</i><br />
<i>Aim to the target and avoid the spikes.</i><br />
<div style="text-align: center;">
<span style="font-style: italic;"><br /></span></div>
<div style="text-align: center;">
<iframe allowfullscreen="" frameborder="0" height="283" src="https://www.youtube.com/embed/QNULYKvHWw0" width="504"></iframe></div>
<i><br /></i>
<b>Design and programming:</b> <a href="https://twitter.com/Imanolea">Imanolea</a><br />
<b>Graphics:</b> <a href="https://twitter.com/seiyouh">Seiyouh</a><br />
<b>System:</b> Game Boy<br />
<br />
<div style="text-align: center;">
<a href="http://gamejolt.com/games/Sheep-Kaboom/267428"><span style="font-size: large;">GAME PAGE</span></a></div>
Imanoleahttp://www.blogger.com/profile/03989722316939496203noreply@blogger.com1tag:blogger.com,1999:blog-2099766654099311467.post-8059244910995267022017-04-09T19:40:00.001+02:002017-10-10T10:02:59.658+02:00Last Crown Warriors #1: Building the scroll system<div style="text-align: justify;">
In the April 1 <a href="https://twitter.com/search?q=%23screenshotsaturday&src=tyah">screenshotsaturday</a> I posted a short video in which the <a href="https://imanoleasgames.blogspot.com.es/search/label/Last%20Crown%20Warriors">Last Crown Warriors</a> scrolling and collision system could be seen in action.</div>
<blockquote class="twitter-tweet" data-lang="es">
<div dir="ltr" lang="en">
Testing the <a href="https://twitter.com/hashtag/LastCrownWarriors?src=hash">#LastCrownWarriors</a> scroll and collision system at MAXIMUM SPEED <a href="https://twitter.com/hashtag/GameBoy?src=hash">#GameBoy</a> <a href="https://twitter.com/hashtag/ScreenshotSaturday?src=hash">#ScreenshotSaturday</a> <a href="https://twitter.com/hashtag/gamedev?src=hash">#gamedev</a> <a href="https://t.co/Cj9iYMg0cd">pic.twitter.com/Cj9iYMg0cd</a></div>
— Imanol Barriuso (@Imanolea) <a href="https://twitter.com/Imanolea/status/848686521301577728">3 de abril de 2017</a></blockquote>
<div style="text-align: justify;">
In the video we can see Lilian moving at a speed of 7 pixels per frame along a stage of 512 by 512 pixels. In this post I will explain the logic behind the scroll system, which as you will see below, allows a scrolling of up to 8 pixels per frame.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The first thing to understand when it comes to setting up a scrolling system for Game Boy is that, in this console, any graphical update that is performed with the LCD <span class="short_text" id="result_box" lang="en"><span class="">switched on</span></span> must occur during the VBlank interrupt (also during the HBlank interrupt, although is not considered for the scroll). And this interrupt marks the beginning of a period of time in which the system is not using the video ram, period in which therefore we have available that memory in order to modify it.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span class="" id="result_box" lang="en">This interruption occurs 59.7 times per second (one for each frame of the game) in a Game Boy. This
graph represents the duration of the interrupt (4,560 clock cycles)
with respect to the total time of the frame (70,224 clock cycles).</span></div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWhSRIlCutvPGxinUiDR_3FJfo4TsLDz61_1z0G7hHTWeSumTmzjUwRnYz4WfNwV-kgpKD4sInKcPVxMq7fwVee-lJxczkLPtT6oeMw75_SxPjNL248SYP5VyBBnuepK4k6XWh3WFppdE/s1600/vblankduration.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="72" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWhSRIlCutvPGxinUiDR_3FJfo4TsLDz61_1z0G7hHTWeSumTmzjUwRnYz4WfNwV-kgpKD4sInKcPVxMq7fwVee-lJxczkLPtT6oeMw75_SxPjNL248SYP5VyBBnuepK4k6XWh3WFppdE/s400/vblankduration.png" width="400" /></a></div>
<div style="text-align: center;">
<span class="" id="result_box" lang="en" style="font-size: x-small;"><span class="">Based on this graph we can conclude that the graphical update must be highly optimized.</span></span></div>
<div style="text-align: justify;">
<br />
<span class="" id="result_box" lang="en"><span class="">And the second thing we need to understand is how the background scrolling works in this system.</span> <span class="">The
scrolling of the background works at a hardware level, that is,
changing the value of a register can alter the position of the background we have loaded into memory.</span> But the size of this
background is limited, 256 by 256 pixels, so for maps that exceed those
dimensions it will need to be modified.</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span class="" id="result_box" lang="en"><span class="">The base of the scroll system will then be the redrawing of the background.</span> <span class="">And
taking into account that the graphic modification should be as optimum
as possible, it only remains to decide which part of the background should be
updated during the interruption.</span> <span class="">In Last Crown Warriors, we update the </span></span><span class="" id="result_box" lang="en"><span class=""><span class="" id="result_box" lang="en"><span class="">visible </span></span>column and row of the part of the background to which we are going.</span> <span class="">For example, if you go up, left, or up and left, we will update the background bar highlighted in the next image.</span> <span class="">The blue box represents the visible background.</span></span></div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfvUWw2eIfnjXbinK-Y0XAVp_srLo5YNqhr12PkUvZKW3pFcm6L2lIF-7Ek2_HqElFyXtwpVS_NNYiEmy9aSCYIGM4Pg45TnhLgfzck7err2On-rGrUIMn3H7oImJmCd1ZN4b-TSEpIac/s1600/bkgUpdate.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="362" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfvUWw2eIfnjXbinK-Y0XAVp_srLo5YNqhr12PkUvZKW3pFcm6L2lIF-7Ek2_HqElFyXtwpVS_NNYiEmy9aSCYIGM4Pg45TnhLgfzck7err2On-rGrUIMn3H7oImJmCd1ZN4b-TSEpIac/s400/bkgUpdate.png" width="400" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span class="" id="result_box" lang="en"><span class="">For the rest of directions we will update the corresponding bar following the same
principle: update the row and column closest to being visible.</span> <span class="">This full modification of column and row allows us to scroll the background up to 8 pixels per iteration.</span></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span class="" id="result_box" lang="en"><span class="">Once we are clear about what tiles need to be replaced, it remains to answer the question of how to do it.</span> <span class="">As we have seen, the time available to modify the video memory is very limited.</span> <span class="">So
in Last Crown Warriors we prepare a data structure with the following
information, in order to minimize the time it takes to replace the tiles
of the background:</span></span></div>
<ul style="text-align: justify;">
<li>byte 0: low byte of the address of the tile to be replaced;</li>
<li>byte 1: high byte of the address of the tile to be replaced;</li>
<li>byte 2: new tile value.</li>
</ul>
<div style="text-align: justify;">
<span class="" id="result_box" lang="en">This structure is repeated for each of the tiles that we have to update, 41 in total. <span class="">Thus,
during the interruption of VBlank we must only execute the following
code, pointing to the beginning of the previously prepared data
structure.</span></span></div>
<br />
<script src="https://pastebin.com/embed_js/DcJAJT6K"></script>
<br />
<div style="text-align: justify;">
<span class="" id="result_box" lang="en"><span class="">We use REPT so that the indicated code is repeated for each of the tiles.</span> <span class="">Discarding a possible loop, which would consume additional processing.</span></span><br />
<br />
<span class="" id="result_box" lang="en"><span class="">Also it is important that in case we use other </span></span><span class="" id="result_box" lang="en"><span class=""><span class="" id="result_box" lang="en"><span class="">Game Boy </span></span>interrupts we execute <i>"ei" (enable interrupts)</i> at the start of them. So we make sure that the VBlank interrupt is called at the right time and that no part of it will ever run outside the VBlank period.</span></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span class="" id="result_box" lang="en"><span class="">And this would be a conceptual explanation of how the scrolling system works in this game.</span> <span class="">In
future posts I will try to cover other aspects of the development. For these posts it will not be necessary to have an advanced knowledge of the system in order to
understand the exposed ideas.</span></span></div>
<script async="" charset="utf-8" src="//platform.twitter.com/widgets.js"></script>Imanoleahttp://www.blogger.com/profile/03989722316939496203noreply@blogger.com6tag:blogger.com,1999:blog-2099766654099311467.post-55699761737658913612017-04-09T19:40:00.000+02:002017-10-10T09:57:09.614+02:00Last Crown Warriors #1: Creando el sistema de scroll<div style="text-align: justify;">
En el <a href="https://twitter.com/search?q=%23screenshotsaturday&src=tyah">screenshotsaturday</a> del 1 de abril publiqué un vídeo corto en el que se podía obervar el sistema de scroll y colisiones de <a href="https://imanoleasgames.blogspot.com.es/search/label/Last%20Crown%20Warriors">Last Crown Warriors</a> en acción.</div>
<blockquote class="twitter-tweet" data-lang="es">
<div dir="ltr" lang="en">
Testing the <a href="https://twitter.com/hashtag/LastCrownWarriors?src=hash">#LastCrownWarriors</a> scroll and collision system at MAXIMUM SPEED <a href="https://twitter.com/hashtag/GameBoy?src=hash">#GameBoy</a> <a href="https://twitter.com/hashtag/ScreenshotSaturday?src=hash">#ScreenshotSaturday</a> <a href="https://twitter.com/hashtag/gamedev?src=hash">#gamedev</a> <a href="https://t.co/Cj9iYMg0cd">pic.twitter.com/Cj9iYMg0cd</a></div>
— Imanol Barriuso (@Imanolea) <a href="https://twitter.com/Imanolea/status/848686521301577728">3 de abril de 2017</a></blockquote>
<div style="text-align: justify;">
En el vídeo podemos ver a Lilian desplazándose a una velocidad de 7 píxeles por frame a lo largo de un escenario de 512 por 512 píxeles. En esta entrada me dedicaré a explicar la lógica que hay detrás del sistema de scroll, que como veréis a continuación, permite un desplazamiento por frame de hasta 8 píxeles.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Lo primero que hay que entender a la hora de plantear un sistema de scroll para Game Boy es que, en esta consola, toda actualización gráfica que se realice con el LCD encendido debe producirse durante la interrupción de VBlank (o durante la interrupción de HBlank, aunque no la tenemos en cuenta para el scroll). Y es que esta interrupción marca el inicio de un periodo de tiempo en el que el sistema no está haciendo uso de la memoria de vídeo, periodo en el que por lo tanto tenemos disponible dicha memoria para modificarla.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Esta interrupción se produce 59,7 veces por segundo (una por cada frame del juego) en una Game Boy. Esta gráfica representa la duración de la interrupción (4.560 ciclos de reloj) respecto al total de tiempo que dura el frame (70.224 ciclos de reloj).</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEje8__qtDmnxM9cZC131IaspbQM7rYUXNsmUI5vladGWeqtrfHtTUxHc87z9pobvsKmXX_HFTcxFRs__Z5_YDbPDP0ePx-u5KUev4l8UkDILo2wOCOCFnDKhGaEpmkK51Ld5RrPR3f9K_s/s1600/vblankduration.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="72" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEje8__qtDmnxM9cZC131IaspbQM7rYUXNsmUI5vladGWeqtrfHtTUxHc87z9pobvsKmXX_HFTcxFRs__Z5_YDbPDP0ePx-u5KUev4l8UkDILo2wOCOCFnDKhGaEpmkK51Ld5RrPR3f9K_s/s400/vblankduration.png" width="400" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">En base a estos datos podemos concluir que la actualización gráfica debe estar altamente optimizada.</span></div>
<div style="text-align: justify;">
<br />
Y lo segundo que necesitamos entender es cómo funciona el scroll de fondos en este sistema. El desplazamiento del fondo funciona a nivel de hardware, es decir, con cambiar el valor de un registro podremos alterar la posición del fondo que tengamos cargado en memoria. Pero el tamaño de este fondo es limitado, de 256 por 256 píxeles, así que para mapas que superen dichas dimensiones será necesario modificarlo.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
La base del sistema de scroll será entonces el redibujado del fondo. Y teniendo en cuenta que la modificación gráfica debe ser lo más óptima posible, queda decidir qué parte del fondo debe actualizarse durante la interrupción. En Last Crown Warriors, actualizamos la columna y la fila visible de la parte del fondo a la que nos dirigimos. Por ejemplo, si nos dirigimos hacia arriba, hacia la izquierda, o hacia arriba y hacia la izquierda, actualizaremos la franja del fondo resaltada en la siguiente imagen. El recuadro azul respresenta en este caso el fondo visible.</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfvUWw2eIfnjXbinK-Y0XAVp_srLo5YNqhr12PkUvZKW3pFcm6L2lIF-7Ek2_HqElFyXtwpVS_NNYiEmy9aSCYIGM4Pg45TnhLgfzck7err2On-rGrUIMn3H7oImJmCd1ZN4b-TSEpIac/s1600/bkgUpdate.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="362" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfvUWw2eIfnjXbinK-Y0XAVp_srLo5YNqhr12PkUvZKW3pFcm6L2lIF-7Ek2_HqElFyXtwpVS_NNYiEmy9aSCYIGM4Pg45TnhLgfzck7err2On-rGrUIMn3H7oImJmCd1ZN4b-TSEpIac/s400/bkgUpdate.png" width="400" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Para el resto de direcciones actualizaremos la franja correspondiente siguiendo el mismo principio: actualizar la fila y columna más próxima a ser visible. Esta modificación íntegra de columna y fila nos permite un desplazamiento del fondo de hasta 8 píxeles por iteración.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Una vez tenemos claro qué tiles hay que sustituir, queda responder a la pregunta de cómo hacerlo. Como hemos visto, el tiempo disponible para modificar la memoria de vídeo es muy limitado. Por lo que en Last Crown Warriors se prepara una estructura de datos con la siguiente información, de cara a reducir al mínimo el tiempo que conlleva sustituir los tiles del fondo:</div>
<ul style="text-align: justify;">
<li>byte 0: parte baja de la dirección del tile a sustituir;</li>
<li>byte 1: parte alta de la dirección del tile a sustituir;</li>
<li>byte 2: nuevo valor del tile.</li>
</ul>
<div style="text-align: justify;">
Esta estructura se repite por cada uno de los tiles que tenemos que actualizar, 41 en total. De esta forma, durante la interrupción de VBlank sólo debemos ejecutar el siguiente código, apuntando al inicio de la estructura de datos previamente preparada.</div>
<br />
<script src="https://pastebin.com/embed_js/DcJAJT6K"></script>
<br />
<div style="text-align: justify;">
Usamos REPT para que el código señalado se repita por cada uno de los tiles. Desechando así un posible bucle, el cual consumiría procesamiento adicional.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Además es importante que en el caso de que usemos otras interrupciones de Game Boy ejecutemos <i>"ei" (enable interrupts) </i>al inicio de las mismas. De este modo nos aseguramos que la interrupción de VBlank se llama en el momento adecuado y que ninguna parte del código con el que actualizamos los gráficos se ejecuta fuera del periodo de VBlank.<br />
<br />
Y esta sería una explicación conceptual de cómo funciona el sistema de scroll en este juego. En próximas entradas intentaré cubrir otros aspectos del desarrollo, de manera que no sea necesario tener unos conocimientos avanzados sobre el sistema para entender las ideas que se expongan.<br />
</div>
<script async="" charset="utf-8" src="//platform.twitter.com/widgets.js"></script>Imanoleahttp://www.blogger.com/profile/03989722316939496203noreply@blogger.com0tag:blogger.com,1999:blog-2099766654099311467.post-89225284007136417922016-12-28T00:27:00.018+01:002023-08-28T20:50:31.346+02:00Games aside #1: Super Game Boy development (step by step)<div style="text-align: justify;">
Throughout this post we will learn to implement some of the features offered by the Super Game Boy, specifically those used by the recently published <a href="https://imanoleasgames.blogspot.com/2016/06/rocket-man-demo.html">Super Game Boy compatible Rocket Man demo</a>. Demo exposed as a local production in the international independent video game contest <a href="http://www.azplaybilbao.com/">AzPlay</a> held last November in Bilbao.</div>
<div style="text-align: justify;">
<span style="font-size: small;"><br /></span></div>
<span id="result_box" lang="en"><span>Before starting I would like to clarify a number of points</span></span>:<br />
<ol style="text-align: justify;">
<li><span id="result_box" lang="en"><span>the program that we will elaborate is programmed in assembler and makes use of <a href="https://github.com/bentley/rgbds">RGBDS </a>for the creation of the ROM;</span></span></li>
<li style="text-align: justify;"><span id="result_box" lang="en"><span>this publication
does not cover the bases of the development for Game Boy in assembler,
but nor does it require an advanced knowledge on the subject.</span> <span>It
can work as an additional lesson to the numerous tutorials that exist on the web in this respect (personal recommendation, <a href="https://avivace.ovh/apps/gbdev/salvage/tutorial_de_ensamblador%20%5bLa%20decadence%5d.html">https://avivace.ovh/apps/gbdev/salvage/tutorial_de_ensamblador%20%5bLa%20decadence%5d.html</a>);</span></span></li>
<li style="text-align: justify;"><span id="result_box" lang="en"><span>according to the
second point, we will work in the implementation of </span></span><span id="result_box" lang="en"><span>additional functions related to the Super Game Boy for an existing base program.</span></span></li>
</ol>
<ol style="text-align: justify;">
</ol>
<div style="text-align: justify;">
This post will cover the use of the following exclusive features of the Super Game Boy:</div>
<ul style="text-align: justify;">
<li>custom frame display;</li>
<li>custom game palettes.</li>
</ul>
<div style="text-align: justify;">
Giving as a result the following Game Boy ROM. </div>
<div style="text-align: justify;">
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfR7SfwFwhDOVt-dcbrhVO3yTcq0KcGfeIr-0yvCTYoRnp9pe35EJRqv5vTtdRjBm0IgtFNA_v5AATzqihmEtRG0rs-ZPTGoTZP-5-MOv8URQmhbCj5hu7RmEgVpiOKvuLi-rOmABbmKQ/s1600/sgbdev.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="280" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfR7SfwFwhDOVt-dcbrhVO3yTcq0KcGfeIr-0yvCTYoRnp9pe35EJRqv5vTtdRjBm0IgtFNA_v5AATzqihmEtRG0rs-ZPTGoTZP-5-MOv8URQmhbCj5hu7RmEgVpiOKvuLi-rOmABbmKQ/s320/sgbdev.png" width="320" /></a></div>
</div>
<div style="text-align: center;">
<span style="font-size: x-small;">Super Game Boy visualization of the ROM</span><br />
<span style="font-size: large;"> <a href="https://drive.google.com/file/d/0B5EtmvQp4iqoT3BJX1dXWFdFSTA/view?usp=drive_link&resourcekey=0-wAHSK8uTGT_kE7DY69GeiA">ROM DOWNLOAD</a> </span></div>
<br />
<div style="text-align: justify;">
<span id="result_box" lang="en"><span>First we should talk about what the Super Game Boy is</span></span>. According to the <i><a href="https://drive.google.com/file/d/0B5EtmvQp4iqoTTJWX3dEekdaVEE/view?usp=drive_link&resourcekey=0-CgdC8gfVkZwJ655WmmO4nA">Game Boy Programming Manual</a></i> (<i>page 124</i>), <span id="result_box" lang="en"><span> it is a device that allows you to enjoy Game Boy software on a television screen</span></span>. <span id="result_box" lang="en"><span>This software (contained in the Game Boy cartridge) can be connected to the Super Game Boy, which operates on a Super Nintendo.</span></span></div>
<div style="text-align: justify;">
<span style="font-size: small;"><br /></span></div>
<div style="text-align: justify;">
<span class="short_text" id="result_box" lang="en"><span>As the text emphasizes</span></span>, Super Game Boy operates on a Super Nintendo. <span id="result_box" lang="en"><span>This cartridge
is a replica of the Game Boy hardware capable of communicating with the
SNES, it helps us inform the home console of the operations we want to
perform and send the necessary data to it, but it is ultimately its
hardware and not ours</span> (<span>the Super Game Boy one) the responsible for processing and applying the unique features offered by this technology.</span> </span><span id="result_box" lang="en"><span>That is, the graphics of the frame for example, obey the limitations of the SNES and not the Game Boy ones.</span></span><br />
<br />
<h2>
<span style="font-size: large;">Preparations</span></h2>
</div>
<div style="text-align: justify;">
<span id="result_box" lang="en">That said, we move on to the preparation of the computer where we are going to develop. <span>This is a list of the elements that we should have ready in our PC with Windows</span></span>:</div>
<ol style="text-align: justify;">
<li>code editor for program editing (personal recommendation, <a href="https://code.visualstudio.com/">Visual Studio Code</a> and the <a href="https://marketplace.visualstudio.com/items?itemName=Imanolea.z80-asm">Z80 Assembly</a> extension);</li>
<li><a href="https://github.com/bentley/rgbds">RGBDS</a> correctly configured as environment variable;</li>
<li><a href="http://www.devrs.com/gb/hmgd/gbtd.html">Game Boy Tile Designer</a> and <a href="http://www.devrs.com/gb/hmgd/gbmb.html">Game Boy Map Builder</a> for graphics and map editing respectively;</li>
<li><span id="result_box" lang="en"><span>Although the
program of this publication is tested in a real Super Game Boy, it is
recommended to have the necessary technology to execute the resulting
ROM in the final hardware.</span> Failing this<span>, emulators like </span></span><a href="http://bgb.bircd.org/">BGB</a> or <a href="http://www.emulator-zone.com/doc.php/snes/bsnes.html">bsnes</a> <span id="result_box" lang="en"><span>can serve to test the developments that are made with this device in mind, but do not guarantee a perfect emulation.</span></span></li>
</ol>
<div style="text-align: justify;">
<span id="result_box" lang="en"><span>Well, it's time to get down to business.</span> <span>As
this post is about development for Super Game Boy and not about
development for Game Boy we will start from a base project whose ROM
offers the following result.</span></span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0ART4xjWC1veH9rLgqDimoBibbH4lsV2eIrI1gkBJ4EkaU0UdYvor6M_SKvh1rB-8l8kChT4DeFs-_rxoKYRxnvASXYrsq3yax7I15RSJqm4wfCfkeBwJma0iGfY6mYKU7SN6urZSzZU/s1600/sgbdev_base.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="288" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0ART4xjWC1veH9rLgqDimoBibbH4lsV2eIrI1gkBJ4EkaU0UdYvor6M_SKvh1rB-8l8kChT4DeFs-_rxoKYRxnvASXYrsq3yax7I15RSJqm4wfCfkeBwJma0iGfY6mYKU7SN6urZSzZU/s320/sgbdev_base.png" width="320" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">A static title screen</span></div>
<div style="text-align: center;">
<span style="font-size: large;"><a href="https://drive.google.com/file/d/0B5EtmvQp4iqoRFQ0Q3pBbUU3VUU/view?usp=drive_link&resourcekey=0-UizN7EDZxa4yUQARyBYOlA">PROJECT DOWNLOAD</a> </span></div>
<br />
<span id="result_box" lang="en"><span>This is the main source file for this template project</span></span>.<br />
<br />
<div style="text-align: justify;">
<script src="//pastebin.com/embed_js/NSjqctii"></script></div>
<br />
<span id="result_box" lang="en">During development it will be important to have some documentation handy. <span>In my opinion, these would be the texts that condense all you need to know when it comes to programming for Super Game Boy:</span></span><br />
<ul>
<li><i><a href="https://drive.google.com/open?id=0B5EtmvQp4iqoTTJWX3dEekdaVEE"><span style="font-size: small;">Game Boy Programming Manual</span></a></i>;</li>
<li><span style="font-size: small;"><i>SGB Functions - GbdevWiki (<a href="http://gbdev.gg8.se/wiki/articles/SGB_Functions">http://gbdev.gg8.se/wiki/articles/SGB_Functions</a>)</i>.</span></li>
</ul>
<span id="result_box" lang="en"><span>Each time I give
information about the Super Game Boy I will try to complement it with
the source of this information, indicating in which part of these two
documents it is.</span></span><br />
<br />
<h2>
<span style="font-size: large;">Making the graphics</span></h2>
<span id="result_box" lang="en">We will begin by freely designing the Super Game Boy frame that we want to apply. <span>Of course, taking into account the following limitations:</span></span></div>
<div style="text-align: justify;">
<ol>
<li><span id="result_box" lang="en"><span>The resolution of the frame must match the resolution of the SNES, ie, 256 pixels wide by 224 pixels high;</span></span></li>
<li><span id="result_box" lang="en"><span>we must leave a
blank space of 160 by 144 pixels in the central part, which is where the
screen of the Game Boy will be displayed;</span></span></li>
<li><span id="result_box" lang="en">the SNES has 8 palettes of 16 RGB 15 bit colors (<i>SGB Functions> Available SNES Palettes</i>). <span>The first four (0-3) are used to color the Game Boy's own graphics and the last four (4-7) for the frame.</span> <span>In the section Frame palettes I explain in more detail this limitation;</span></span></li>
<li><span id="result_box" lang="en"><span></span></span><span id="result_box" lang="en"><span>we can not use
more than 256 tiles of 8 by 8 pixels at the time of designing the frame
(the tiles of the SNES are 8x8 and we have a byte to map them. The
good thing is that these tiles can be flipped horizontally and
vertically.</span></span></li>
</ol>
<br />
<h2>
Frame palettes</h2>
<span id="result_box" lang="en">As we have commented we have at our disposal 4 palettes of 16 colors for the frame. <span>Although
not exactly, according to the official documentation we have the 4-6
(<i>Game Boy Programming Manual> page 162</i>), ie 3 palettes.</span> <span>Anyway we can also use the 7. But some emulators will not recognize this last palette correctly.</span></span><br />
<br />
<span id="result_box" lang="en">15 bit RGB color, what does this mean? We have 5 bits to indicate the level of red, 5 for green and 5 for blue. That is, an accuracy of 0-31 to define the intensity of each of the colors. <span>If
we have an RGB color of 24 bit (the predominant format) that we want to
use on any of our palettes we would have to round up the value from 0 to
255 that we have for color to the equivalent between 0 and 31.</span></span><br />
<br />
<span id="result_box" lang="en" tabindex="-1">We have said 16 colors, must be qualified: color 0 is shared (<i>SGB Functions> Color 0 Restriction</i>)! This means that if the color 0 of the last palette we assign is red, the color 0 of the other graphics will change to red. And we have 16 colors just in case we want to spend the memory needed to store 4bpp graphics (4 bits per pixel) in the Game Boy. <span>If 2bpp is enough then we have four colors per palette with the color 0 shared, but the graphics will occupy half in memory.</span></span><br />
<br />
<span id="result_box" lang="en">There are many games that accept the limitation of four colors per palette in the frame showing the color 0 to save memory. <span>As for example it happens with the frame of Pokémon Blue.</span></span><br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqZSHiQ2PGTt0yV7E3bdw2Ph-AO0gTgpmVncZQZWI2g9HUCSPlj2eduR6QALMxo9xL-XedHc4fRS4PNUc7aY98XT-TS-IewP7j89uFpXl4piFWjI2LOuc5pRNnrN2owvXfyoCrUbDBy_w/s1600/pokemonazul.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="280" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqZSHiQ2PGTt0yV7E3bdw2Ph-AO0gTgpmVncZQZWI2g9HUCSPlj2eduR6QALMxo9xL-XedHc4fRS4PNUc7aY98XT-TS-IewP7j89uFpXl4piFWjI2LOuc5pRNnrN2owvXfyoCrUbDBy_w/s320/pokemonazul.png" width="320" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">Comparing the two red squares we see that the frame shows the color 0 shared with the rest of the palettes. Using four colors per tile (2bpp)</span><br />
<div style="text-align: left;">
<span style="font-size: x-small;"><br /></span></div>
</div>
<div style="text-align: left;">
<h2>
Our frame</h2>
</div>
This is our frame.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJd7tvcULAAWamoegu1qAPyYlc15QWRBwCAShOZ4qDSh2rg5lWliKHA2FM-xGso1YATscDZWcmGgoyPJA44-aZb7FV7P8X2BRGqBzMbZ1-14mfflcnEGvLY-WBvGFImBsGDWkby-5Qwy4/s1600/frame.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="350" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJd7tvcULAAWamoegu1qAPyYlc15QWRBwCAShOZ4qDSh2rg5lWliKHA2FM-xGso1YATscDZWcmGgoyPJA44-aZb7FV7P8X2BRGqBzMbZ1-14mfflcnEGvLY-WBvGFImBsGDWkby-5Qwy4/s400/frame.png" width="400" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">256 by 224 pixels frame</span> </div>
<br />
These our tiles.<br />
<br />
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-kCxxy9m3SS-aOezG5iJhqHUnx45443xhVK69lTU4REtSYmYuZ-TFEt6hlsvSvxcQtt31jJzgZtjm_VvuNNJCyOR68-BwxXC_GcVPNA9znf3SK4ChCFsJsHSYty_OVPI7qFImyYyWG2I/s1600/tiles.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-kCxxy9m3SS-aOezG5iJhqHUnx45443xhVK69lTU4REtSYmYuZ-TFEt6hlsvSvxcQtt31jJzgZtjm_VvuNNJCyOR68-BwxXC_GcVPNA9znf3SK4ChCFsJsHSYty_OVPI7qFImyYyWG2I/s400/tiles.png" width="228" /></a> </div>
<div style="text-align: center;">
<span style="font-size: x-small;">176 tiles (including tile null one) of the 256 available </span></div>
<br />
<span class="short_text" id="result_box" lang="en"><span>And these our palettes</span></span>.<br />
<br />
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-W_oL44qtSG1Vvd49KltlFV3Ue91E_7p0ADLMcKzDe9WHbDgyu9NE4xj2QWJkoEdxhq2DJLv7ns5Wkm7yi5h2JZsQFwhHwE3sJwK43-4SNLVKHVbQxNUinygZXN5Sj0QJGQhsJfpqq6A/s1600/palettes.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="70" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-W_oL44qtSG1Vvd49KltlFV3Ue91E_7p0ADLMcKzDe9WHbDgyu9NE4xj2QWJkoEdxhq2DJLv7ns5Wkm7yi5h2JZsQFwhHwE3sJwK43-4SNLVKHVbQxNUinygZXN5Sj0QJGQhsJfpqq6A/s400/palettes.png" width="400" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">Palettes 4-6 used to represent the colors of each of the tiles</span></div>
<br />
<span id="result_box" lang="en">Three palettes of 16
colors (4bpp), the color 0 (first column) is not used so we don't have
to share it with the palettes that we are going to use in the graphics
of the Game Boy. Because of the characteristics of the development, this is the color distribution that has remained on the three palettes. <span>Only one might as well have been used, since they have many colors in common.</span></span><br />
<br />
<span id="result_box" lang="en" tabindex="-1"><span>And now, it's time to turn these specifications into data that we can add to our program.</span></span><br />
<br />
<h2>
Tiles file</h2>
<span id="result_box" lang="en" tabindex="-1"><span>The graphic data of the tiles will be created with</span></span> <a href="http://www.devrs.com/gb/hmgd/gbtd.html">Game Boy Tile Designer</a>. <span id="result_box" lang="en" tabindex="-1"><span>In our frame some of the palettes use more than 4 colors so our graphics should be 4bpp.</span></span><br />
<br />
<span id="result_box" lang="en" tabindex="-1"><span>If
the graphics are 2bpp we simply draw the tiles with the editor taking
into account that the colors we choose for the values 0, 1, 2, and 3
will correspond to the colors 0, 1, 2 and 3 of the palette</span> that we have specified for that tile.</span><br />
<br />
<div style="text-align: center;">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6YV8GLz_NPcXotgns4Hj5XzFN2jqcv9R7FtxVtVAppY1YDXg5QAu25-FMFDtXODzOAqfZp8deJhAQ1wrAlwHBdR6UgIA6np9ENztTuZePisKE5zpmrIvpnrYpeCp06cqw34R3eMvHces/s1600/2bpp.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6YV8GLz_NPcXotgns4Hj5XzFN2jqcv9R7FtxVtVAppY1YDXg5QAu25-FMFDtXODzOAqfZp8deJhAQ1wrAlwHBdR6UgIA6np9ENztTuZePisKE5zpmrIvpnrYpeCp06cqw34R3eMvHces/s1600/2bpp.png" width="512" /></a></div>
</div>
<div style="text-align: center;">
<span style="font-size: x-small;">Left: <a href="http://www.devrs.com/gb/hmgd/gbtd.html">Game Boy Tile Designer</a> tile; center: palette specified for the tile; Right: tile display in Super Game Boy</span> </div>
<br />
<span id="result_box" lang="en" tabindex="-1">The SNES
4bpp graphics can also be created in a simple way using the same
program: drawing two consecutive Game Boy tiles for each tile of Super NES. <span>The first for bit planes 1 and 2, and the second one for numbers 3 and 4.</span></span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDVXT1BsjafpgQG8x-9jhJ0nRcg9IgbF7AAGoklxiA73RQncdlsh9SAHJQ30ununTy2dltW9mMLW20RxZDB4qRS2m7N3GIWzCfyyvL0rcukHvKhrAq_zw6IGo8ScmX08DyXUHvQedvmg4/s1600/4bpp.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDVXT1BsjafpgQG8x-9jhJ0nRcg9IgbF7AAGoklxiA73RQncdlsh9SAHJQ30ununTy2dltW9mMLW20RxZDB4qRS2m7N3GIWzCfyyvL0rcukHvKhrAq_zw6IGo8ScmX08DyXUHvQedvmg4/s1600/4bpp.png" width="512" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">We can combine two Game Boy pixels (2 bits) to create a SNES pixel (4 bits)</span></div>
<br />
<span id="result_box" lang="en" tabindex="-1"><span>Although we use 4bpp graphics we should also have a .gbr file that dedicates a single Game Boy tile per SNES tile</span></span>.<span id="result_box" lang="en" tabindex="-1"> <span>And we will use it when elaborating the map of the frame with</span></span> <a href="http://www.devrs.com/gb/hmgd/gbmb.html">Game Boy Map Builder</a>, in this way<span id="result_box" lang="en" tabindex="-1"><span> we will reference the number of the tile as it would do the SNES and not the Game Boy.</span></span><br />
<br />
<span id="result_box" lang="en" tabindex="-1"><span>The result of the elaboration of these tilesets with </span></span><a href="http://www.devrs.com/gb/hmgd/gbtd.html">Game Boy Tile Designer</a> is the following: <span id="result_box" lang="en" tabindex="-1"><span>the tileset that will store the graphics to use in the frame</span></span> (<a href="https://drive.google.com/file/d/0B5EtmvQp4iqoVlNELU9tb2NnZDA/view?usp=drive_link&resourcekey=0-vlFEQU4CoVLEepRfRsUWmg">FILE DOWNLOAD</a>) <span id="result_box" lang="en" tabindex="-1"><span>and the tileset whose only function will be to contain an index of the tiles to be mapped later</span></span> (<a href="https://drive.google.com/file/d/0B5EtmvQp4iqoejBtODhwQTB0dUE/view?usp=drive_link&resourcekey=0-9OzbdkwgeF0P1sUQNIDXFw">FILE DOWNLOAD</a>). <span id="result_box" lang="en" tabindex="-1"><span>Within the project, we will place these two files in</span></span> res/tiles/.<br />
<br />
<span id="result_box" lang="en" tabindex="-1">And with the following configuration, we export the 4bpp tileset to obtain the necessary data file for the project. <span>We
delete the section declaration and automatically generated tags and
place the resulting file in dev/data/tiles/ as sgb_tileset.z80</span></span> (<a href="https://drive.google.com/file/d/0B5EtmvQp4iqoYjBhWHc2cDRJcFE/view?usp=drive_link&resourcekey=0-rvD4B1CcY3oA_MnhsRNGDA">FILE DOWNLOAD</a>).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh80c24irHUjXo9f6Tv1avuU9-BLdGavQT4Oz319PcS_BuPUvwZKQOMsTVe7E59nmhiT5z3vR0k18lPXl_jw2qzYvMMf7mcVgVpUXjh8-Eu4KzOuYjzBsQqfMab45_iJ3E2QQQveP5f93E/s1600/exportconfig.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh80c24irHUjXo9f6Tv1avuU9-BLdGavQT4Oz319PcS_BuPUvwZKQOMsTVe7E59nmhiT5z3vR0k18lPXl_jw2qzYvMMf7mcVgVpUXjh8-Eu4KzOuYjzBsQqfMab45_iJ3E2QQQveP5f93E/s1600/exportconfig.png" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">We generate a .z80 file compatible with RGBDS</span></div>
<div style="text-align: center;">
<br /></div>
<h2>
Map file</h2>
Now, with <a href="http://www.devrs.com/gb/hmgd/gbmb.html">Game Boy Map Builder</a>, we will build the frame. <span id="result_box" lang="en" tabindex="-1"><span>We
must associate it with the .gbr file of the tileset with the correct
indexes, the one that uses a single tile of Game Boy per tile of Super NES.</span> <span>Remembering the fact that the dimensions of the frame are 256 by 224 pixels, which means 32 by 28 tiles.</span> <span>So once we open the program we go to "File> Map properties ..." and we take care of adapting dimensions and tileset.</span></span><br />
<span style="font-size: small;"></span><br />
<div class="separator" style="clear: both; text-align: center;">
<span style="font-size: small;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUy2J2t3x5uuc2_z0kh8ieOQiM8gnyJwaa48UPKP0phAxAxUbd4-hEVKR8G8bHB7lJIzj4x1KEU7vWNdFK8sFqDvdzOx1Fkz5WM2ydarpJeNV4AyN7ic7GXs0EshfIgrO7jwczYglYcLs/s1600/mapproperties.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUy2J2t3x5uuc2_z0kh8ieOQiM8gnyJwaa48UPKP0phAxAxUbd4-hEVKR8G8bHB7lJIzj4x1KEU7vWNdFK8sFqDvdzOx1Fkz5WM2ydarpJeNV4AyN7ic7GXs0EshfIgrO7jwczYglYcLs/s1600/mapproperties.png" /></a></span></div>
<div style="text-align: center;">
<span style="font-size: small;"><span style="font-size: x-small;">The tileset we use here only serves as a visual reference when it comes to mapping the tiles</span></span></div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: justify;">
<span id="result_box" lang="en" tabindex="-1">As I mentioned earlier, the SNES tiles can be flipped either horizontally (X Flip) or vertically (Y Flip). Additionally each of the tiles will be associated with one of the palettes we have specified. That's why we need to define additional attributes for each tile we place on our map. <span>We can do this in "File> Location properties ...".</span></span></div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJ_OxPdXo5x48GP0ooVWlWD_um8vKIe8aEthI8-YLCRVEwMR7WJMuxu6pgyC9aW9CbJ1sag4ghLgj4Brdi4DeuqmxvuEIDz87_fcBV31Tlw5-QLI-DIvWJ-v4QY-5pKVyCBgB5mPxCXpQ/s1600/locationproperties.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJ_OxPdXo5x48GP0ooVWlWD_um8vKIe8aEthI8-YLCRVEwMR7WJMuxu6pgyC9aW9CbJ1sag4ghLgj4Brdi4DeuqmxvuEIDz87_fcBV31Tlw5-QLI-DIvWJ-v4QY-5pKVyCBgB5mPxCXpQ/s1600/locationproperties.png" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">We do not define the vertical flip (Y Flip) because it is not used in our frame</span></div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: justify;">
<span id="result_box" lang="en" tabindex="-1">As we will
see the flip is defined as a single bit (1 flipped, 0 not flipped)
and the palette with 2 (range of 0 to 3 that corresponds respectively
with the palettes from 4 to 7), these will be the 2 less significant bits of the 3 that are later assigned to the palette. <span>The
third bit, the most significant bit, will always return the value of 1. This gives
us a real range of values from 4 to 7 when exporting.</span></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span id="result_box" lang="en" tabindex="-1"><span>Now
we map the tiles of the frame, and define their location properties
through the fields available in the bottom row of the editor.</span></span></div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEix6kmVSYMH6l-urOi4hhsWudL23qhHuS17VA8r3VLZzoCKfy9tBFiLHJbqfYVmnpmWFb4rHvMKqrj_YrQOkNjV6OlxQAEeVZm6up6kapcGw12wbKPh_31WwZxKCnCn759IALAq3KnDftg/s1600/bordermap.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEix6kmVSYMH6l-urOi4hhsWudL23qhHuS17VA8r3VLZzoCKfy9tBFiLHJbqfYVmnpmWFb4rHvMKqrj_YrQOkNjV6OlxQAEeVZm6up6kapcGw12wbKPh_31WwZxKCnCn759IALAq3KnDftg/s1600/bordermap.png" width="512" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">We recall that we must leave a space of null tiles in the position of the Game Boy screen</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span id="result_box" lang="en" tabindex="-1"><span>As a result, we have a .gbm file with the map design that will conform the frame </span></span>(<a href="https://drive.google.com/file/d/0B5EtmvQp4iqoc2ZQc3FSVDZUM3c/view?usp=drive_link&resourcekey=0-fKRxLcDHSLZM-Dt2BF4MPQ">FILE DOWNLOAD</a>), <span id="result_box" lang="en" tabindex="-1"><span>we place it in</span></span> res/maps/. <span id="result_box" lang="en" tabindex="-1"><span>As
a point, I would like to clarify that the first thing to do when opening the map in
Game Boy Map Builder is to reference the tileset of the indexes through
"File> Map properties ...".</span></span></div>
<br />
<span id="result_box" lang="en" tabindex="-1">Now we are going to generate the data file relative to the map through "File> Export to ...". Let's make sure that we comply with the map format specification (<i>SGB Functions> SGB Command 14h - PCT_TRN</i>). <span>In the export options we will include the location properties we defined above.</span> <span>This would be the official specification regarding our export configuration.</span></span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmwj1Zn1VFJOPQCdkRxlfp_RO1EUUF6iJUMcxWOgZCq8NDPdiufixW7kKlC3WlxSGk44mV-b3e5uct1WYZDz4ra12NOX6oYyA6ks4Sugkv8DrSy6wQH2AnpEHuUGpvtCVm9aGLKVuUtYE/s1600/bkmapentry.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmwj1Zn1VFJOPQCdkRxlfp_RO1EUUF6iJUMcxWOgZCq8NDPdiufixW7kKlC3WlxSGk44mV-b3e5uct1WYZDz4ra12NOX6oYyA6ks4Sugkv8DrSy6wQH2AnpEHuUGpvtCVm9aGLKVuUtYE/s1600/bkmapentry.png" width="512" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">Official frame tiles format specification</span></div>
<div style="text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-size: x-small;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjH3kZghZq1ToCoZrVjJ75yFmZAB7pAK-pLJ03dBhOLAONgmAkDle5FRCxWItYs06cihKRw7rEYGSTgKwvUKqfPpeh7q5XkXVjLb_imPo4NusNrKFqhP54-4ZTpb-oOdsWl8QCBrr49x2A/s1600/mapexportconfig.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjH3kZghZq1ToCoZrVjJ75yFmZAB7pAK-pLJ03dBhOLAONgmAkDle5FRCxWItYs06cihKRw7rEYGSTgKwvUKqfPpeh7q5XkXVjLb_imPo4NusNrKFqhP54-4ZTpb-oOdsWl8QCBrr49x2A/s1600/mapexportconfig.png" /></a></span></div>
<div style="text-align: center;">
<span style="font-size: x-small;">In the case of the Y Flip property, we ignore it occupying its place with a 0</span></div>
<div style="text-align: center;">
<br />
<div style="text-align: justify;">
<div style="text-align: justify;">
<span id="result_box" lang="en"><span>Once exported, we delete the section declaration and the resulting data tags and place it in dev/data/maps/</span></span> (<a href="https://drive.google.com/file/d/0B5EtmvQp4iqoMUNoZ1JIUVY5S2c/view?usp=drive_link&resourcekey=0-Rifhjhkh1wnhzCIol4C2Tw">FILE DOWNLOAD</a>).<span style="font-size: x-small;"> </span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span id="result_box" lang="en"><span>We already have all the graphic files ready, only the data from the palettes is missing.</span> <span>To do this we will now create the file sgb.z80, which we will place it dev/data/.</span> <span>Here
we are going to write the definitions of the packets that we will
send to the SNES and in this case also the macro of the RGB of 15 bits
that will be used for the colors of our palettes.</span></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<script src="//pastebin.com/embed_js/7bUCCR4G"></script>
</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: left;">
<div style="text-align: justify;">
<span id="result_box" lang="en">The three parameters of the macro correspond respectively to the value of red, green and blue that we want to give to each color. <span>Well, now we have to specify palettes based on this macro.</span></span><br />
<br />
<span id="result_box" lang="en"><span>We must place
the palettes next to the map data (<i>SGB Functions> SGB Command 14h -
PCT_TRN</i>), so we will create a file in dev/data/maps called
sgborder.z80</span></span> (<a href="https://drive.google.com/file/d/0B5EtmvQp4iqoalgwZUNsQ2RDcGM/view?usp=drive_link&resourcekey=0-Io5hB-PDygrtbooQy9z0sA">FILE DOWNLOAD</a>), <span id="result_box" lang="en"><span>there we will adapt our palettes to the</span> <span>specification.</span></span><br />
<span style="font-size: small;"> </span><br />
<div class="separator" style="clear: both; text-align: center;">
<span style="font-size: small;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzd4cYy4NegO5l76jII7ZU4oeKKbAHG6DJDd8XCuf9-OdHiMVdd6IbeXeHSL56D1LB7UpgfFCY-Zu-OOrIr6nCCzRVpUu2a9q8_gdzzfm8FtLTx8kwW6yE1SXHcKljkiAPtqsJyN3Fh0c/s1600/bkgmapdata.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzd4cYy4NegO5l76jII7ZU4oeKKbAHG6DJDd8XCuf9-OdHiMVdd6IbeXeHSL56D1LB7UpgfFCY-Zu-OOrIr6nCCzRVpUu2a9q8_gdzzfm8FtLTx8kwW6yE1SXHcKljkiAPtqsJyN3Fh0c/s1600/bkgmapdata.PNG" width="512" /></a></span></div>
<div style="text-align: center;">
<span style="font-size: small;"><span style="font-size: x-small;">The map must be 32x32 tiles but the last 4 rows are not part of the screen and are unnecessary</span></span></div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
<span style="font-size: small;"><span style="font-size: x-small;"> </span></span><span style="font-size: small;"><span style="font-size: x-small;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-W_oL44qtSG1Vvd49KltlFV3Ue91E_7p0ADLMcKzDe9WHbDgyu9NE4xj2QWJkoEdxhq2DJLv7ns5Wkm7yi5h2JZsQFwhHwE3sJwK43-4SNLVKHVbQxNUinygZXN5Sj0QJGQhsJfpqq6A/s1600/palettes.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-W_oL44qtSG1Vvd49KltlFV3Ue91E_7p0ADLMcKzDe9WHbDgyu9NE4xj2QWJkoEdxhq2DJLv7ns5Wkm7yi5h2JZsQFwhHwE3sJwK43-4SNLVKHVbQxNUinygZXN5Sj0QJGQhsJfpqq6A/s1600/palettes.png" /> </a></span></span></div>
<div style="text-align: center;">
<span style="font-size: x-small;">We remember the specification of our palettes</span><br />
<br />
<script src="//pastebin.com/embed_js/Qg9DtajE"></script> <span style="font-size: small;"><span style="font-size: x-small;">The first color of each palette (color 0) is specified but not used</span></span><br />
<div style="text-align: left;">
<div style="text-align: justify;">
<h2>
Game palettes</h2>
<span id="result_box" lang="en" tabindex="-1">Finally we are going to add to sgb.z80 the declaration of the palette that we will use for the graphics of the game itself. Recall that while the 4-7 palettes are used for the frame, the 0-3 palettes are used for the graphics of the game. <span>The Game Boy's monochrome graphics have a 4 color limitation so we can only use 4 colors in this palette.</span></span></div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyHtnYLp-PBbHWcS8F_uL3CqoAMFxFZCumThEBL4kAV4iZ5kFdhweZ5u5kWrFuU-6OC4a2RfuXcu6Yx8XnX9BuL394nhk3cdrejgS7_QkhZ4vDGhBAZc02GPuIMXaySbA3HPuwb2AvZII/s1600/gamepalettes.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyHtnYLp-PBbHWcS8F_uL3CqoAMFxFZCumThEBL4kAV4iZ5kFdhweZ5u5kWrFuU-6OC4a2RfuXcu6Yx8XnX9BuL394nhk3cdrejgS7_QkhZ4vDGhBAZc02GPuIMXaySbA3HPuwb2AvZII/s1600/gamepalettes.png" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">We will only use one of the four palettes assignable to the Game Boy game</span></div>
<div style="text-align: center;">
<br />
<script src="//pastebin.com/embed_js/V2FTKJJF"></script></div>
<div style="text-align: center;">
<span style="font-size: x-small;">The color 0 that we define should be the one we want to share with the rest of the palettes</span></div>
<br />
<div style="text-align: justify;">
As we have already specified all the necessary graphic files, it is time to add them to the memory bank that we have declared in main.asm.</div>
<br />
<script src="//pastebin.com/embed_js/Medrfxg3"></script>
<span style="font-size: large;"> </span><br />
<h2>
<span style="font-size: large;">Logic programming</span></h2>
<br />
<h2>
Auxiliary definitions</h2>
<div style="text-align: justify;">
There are two ways of sending information to the Super NES (<i>Game Boy Programming Manual> page 127</i>), through registers P14 and P15 and through the Game Boy's own VRAM (VRAM transfer). Both involve the use of commands. So let's start by defining in the sgb.z80 file the macros of the commands we are going to use (we have a definition of what each command does in <i>Game Boy Programming Manual> page 132</i> and <i>SGB Functions> SGB Command Summary</i>):</div>
<ol>
<li style="text-align: justify;">MLT_REQ, <span id="result_box" lang="en" tabindex="-1"><span>makes a multiplayer request, it will be used to detect if the software is running on a Super Game Boy</span></span>;</li>
<li style="text-align: justify;">CHR_TRN, <span id="result_box" lang="en" tabindex="-1"><span>we will use it to copy the tiles from the frame to the SNES RAM (with a VRAM transfer)</span></span></li>
<li style="text-align: justify;">PCT_TRN, <span id="result_box" lang="en" tabindex="-1"><span>we will use it to copy the frame map to the SNES RAM (with a VRAM transfer);</span></span></li>
<li style="text-align: justify;">PAL_SET, <span id="result_box" lang="en" tabindex="-1"><span>will assign the palette that we have defined for the graphics of the game;</span></span></li>
<li style="text-align: justify;">PAL_TRN, <span id="result_box" lang="en" tabindex="-1"><span>will copy the palette that we have defined for the game graphics to the SNES RAM (with a VRAM transfer);</span></span></li>
<li style="text-align: justify;">MASK_EN, <span id="result_box" lang="en" tabindex="-1"><span>will freeze the screen during communication processes with the Super Game Boy, and unfreeze it upon completion;</span></span></li>
<li style="text-align: justify;"><span id="result_box" lang="en" tabindex="-1"><span>Finally
we will define eight data packets that we will send to initialize the
communication as recommended in the official documentation (<i>Game Boy
Programming Manual> page 178</i>).</span></span></li>
</ol>
<ol>
</ol>
<div style="text-align: justify;">
<br />
<script src="//pastebin.com/embed_js/a1CGgAmx"></script>
<br />
<span id="result_box" lang="en" tabindex="-1"><span>And with this we finally complete the auxiliary file sgb.z80</span></span> (<a href="https://drive.google.com/file/d/0B5EtmvQp4iqoS05DeEU4VUNGYUE/view?usp=drive_link&resourcekey=0-LTsA5OHElcDcQmVgrmP8xA">FILE DOWNLOAD</a>).<br />
<br />
<span id="result_box" lang="en" tabindex="-1">As a
prerequisite to logic programming, we must write a 0x03 in the </span><span id="result_box" lang="en" tabindex="-1"><span id="result_box" lang="en" tabindex="-1">0x0146 </span>address of our ROM to indicate that we support the functionality of Super Game
Boy (<i>Game Boy Programming Manual> page 178</i>). <span>We already have parameterized this address in gbhw.inc, so we modified the second parameter of the header in main.asm.</span></span><br />
<br />
<script src="//pastebin.com/embed_js/uHXEp9R9"></script></div>
<br />
<h2>
Communication implementation</h2>
<div style="text-align: justify;">
<span id="result_box" lang="en" tabindex="-1">Let's explain with a practical example how we have defined the macros of the packets in sgb.z80. <span>Let's
take our macro from MLT_REQ and compare it to the memory specification
of the command (<i>SGB Functions> SGB Command 11h - MLT_REQ</i>).</span></span></div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1jz4e32mkBESYteZaq4Ps_VzoEDrlTl2DBuOcvxE4RYB5Hu2y9CtXAQ3NsjUVmNpRqlJ1vPuWNUhI44LwWrB-HLWK2RVCggWBIuzychrncLPX43Een8_6dUMQ_8JIRmBaj7qBQWRrvkw/s1600/mlt_reqspec.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1jz4e32mkBESYteZaq4Ps_VzoEDrlTl2DBuOcvxE4RYB5Hu2y9CtXAQ3NsjUVmNpRqlJ1vPuWNUhI44LwWrB-HLWK2RVCggWBIuzychrncLPX43Een8_6dUMQ_8JIRmBaj7qBQWRrvkw/s1600/mlt_reqspec.png" width="512" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">As we see the Super Game Boy allows a multiplayer mode of up to 4 players with the SNES Super 5 multi-player adapter </span></div>
<div style="text-align: center;">
<br /></div>
<script src="//pastebin.com/embed_js/vjga5uHK"></script>
<br />
<div style="text-align: justify;">
<span id="result_box" lang="en" tabindex="-1">We see how byte 1 defines the number of players requested in the Super Game Boy multiplayer mode. <span>We parameterized this byte in our macro and specified with two labels the two variants that we will use in our program.</span></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span id="result_box" lang="en" tabindex="-1">All commands are made up of 16 bytes (128 bits), which is the size of the data packet that we can send. So we only send one packet per command. <span>The
number of packets per transfer can be specified through the three least significant bits of byte 0 of the first packet (as we see in the
specification, byte 0: Command * 8, which happens to occupy the 5 most significant bits +</span> <span>Length, which occupies the remaining 3 bits), so we can send from 1 to 7 packets per transfer.</span> <span>We
will represent the possibility of sending more than one packet per
command in the code, but in the resulting program we do not use this functionality.</span></span><br />
<br />
<span id="result_box" lang="en" tabindex="-1"><span>Now we will describe the process of sending each packet as explained on <i>page 128</i> of the <i>Game Boy Programming Manual</i>.</span> <span>Sending made
through bits 4 and 5 of the Game Boy's P1 register (0xFF00), these bits
correspond respectively to the output ports P14 and P15:</span></span><br />
<ol>
<li><span id="result_box" lang="en" tabindex="-1"><span>we start the communication by putting to</span></span> 0 P14 and P15;</li>
<li><span id="result_box" lang="en" tabindex="-1"><span>we send the 128 bits of the packet by putting to</span></span> 0 P14 and to 1 P15 if we want to send a 0 and to 1 P14 and 0 P15 if we want to send a 1;</li>
<li><span class="short_text" id="result_box" lang="en" tabindex="-1"><span>we send a 0 in bit 129 to close the communication</span></span> (P14 to 0 and P15 to 1).</li>
</ol>
<span id="result_box" lang="en" tabindex="-1"><span>The following list of rules must be taken into account</span></span>:<br />
<ol>
<li><span id="result_box" lang="en" tabindex="-1">the values we write in P14 and P15 must be kept for 5μs, and between writtings we must set P14 and P15 to 1 for at least 15μs. <span>Considering
that a Game Boy clock cycle already lasts more than 23μs, we ignore the
times, but note that we must write a 1 on both ports for each bit sent;</span></span></li>
<li><span id="result_box" lang="en" tabindex="-1">between sending one packet and the next we should wait for a minimum of 60 msec (about 4 frames of Game Boy). <span>The "sgbpackettransfer_wait" routine will take care of this wait.</span></span></li>
</ol>
<span id="result_box" lang="en" tabindex="-1"><span>With all of this in mind, this is our routine of sending packets, which we add to main.asm</span></span>.<br />
<br />
<script src="//pastebin.com/embed_js/ES678Mkf"></script>
<br />
<span id="result_box" lang="en" tabindex="-1"><span>The first functionality that will use this packet sending routine is the one that recognizes whether or not we are in a Super Game Boy.</span> <span>We will do it the following way (which is the recommended way in <i>SGB Functions> Detecting SGB hardware</i>):</span></span><br />
<ol>
<li><span id="result_box" lang="en" tabindex="-1">we will
read the identifier of the register P1, which in addition to serving to send
information through the ports is the register that returns the information
of the joypad of the Game Boy. <span>By default, its reading returns the identifier of the joypad;</span></span></li>
<li><span id="result_box" lang="en" tabindex="-1"><span>we request the two player mode of Super Game Boy by sending the command packet MLT_REQ with two players as the parameter;</span></span></li>
<li><span id="result_box" lang="en" tabindex="-1">we re-read the identifier of the register P1. <span>If it is the same identifier, it means that the two player mode has not been selected and that therefore we are not in a SGB</span></span>.</li>
</ol>
We place the following code in main.asm.<br />
<br />
<script src="//pastebin.com/embed_js/dgk7x7Mc"></script>
<br />
<span id="result_box" lang="en" tabindex="-1"><span>The
following routine will be called "init_sgb_default", and does the sending of the initialization packets recommended by the <i>Game Boy
Programming Manual</i> (<i>page 178</i>).</span> <span>We also add it to main.asm.</span></span><br />
<br />
<script src="//pastebin.com/embed_js/bURzbN55"></script><br />
<span id="result_box" lang="en" tabindex="-1">The transfer commands CHR_TRN, PCT_TRN, and PAL_TRN use the VRAM transfer to copy their data to the SNES RAM. <span>Here are the steps we must follow to perform this type of transfer (as explained in <i>SGB Functions> SGB VRAM Transfers</i>):</span></span><br />
<ol>
<li><span id="result_box" lang="en" tabindex="-1"><span>if
we do not want the data to be displayed on the screen of the Game Boy
we must have previously configured a mask for the LCD of the Game Boy by
making use of the command MASK_EN;</span></span></li>
<li><span id="result_box" lang="en" tabindex="-1"><span>we disable interrupts and turn off the LCD, to avoid that the graphics we want to send are corrupted;</span></span></li>
<li><span id="result_box" lang="en" tabindex="-1">we assign
the default values to the background palette of the Game Boy,
which translates to writing 0xE4 in the palette register that is
at 0xFF47 (0 white, 1 light gray, 2 dark gray, 3 <span>black);</span></span></li>
<li><span id="result_box" lang="en" tabindex="-1"><span>we copy
the 4KB of data that we want to send to the visible background of the Game Boy LCD, the background address begins at 0x9800</span></span>;</li>
<li><span id="result_box" lang="en" tabindex="-1">we send the transfer command, either CHR_TRN, PCT_TRN or PAL_TRN. <span>The data displayed in the visible background of the Game Boy will be sent to the SNES.</span></span></li>
</ol>
<span id="result_box" lang="en" tabindex="-1">Before showing the code of the routine, </span><span id="result_box" lang="en" tabindex="-1"><span class="short_text" id="result_box" lang="en" tabindex="-1"><span>a little more information about</span></span> on MASK_EN. <span>It is usually used at the beginning of the program to hide the actual display of the Game Boy LCD during data transfer.</span></span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNLT0cBtDT_zYHSbOx_PbxsNEZEltJx9ihNcGo0JRsX8lrtcMkmqV7_E3s4OylvZYDue9zDBbosCspWg_WqemxtlT0xFR2xyOtnY9vVSxG-MD1yCYM7jks8b0vWOJt4QHA06uz2kqofgA/s1600/mask_enspec.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNLT0cBtDT_zYHSbOx_PbxsNEZEltJx9ihNcGo0JRsX8lrtcMkmqV7_E3s4OylvZYDue9zDBbosCspWg_WqemxtlT0xFR2xyOtnY9vVSxG-MD1yCYM7jks8b0vWOJt4QHA06uz2kqofgA/s1600/mask_enspec.png" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">(<i>SGB Functions > SGB Command 17h - MASK_EN</i>) </span></div>
<br />
<span id="result_box" lang="en" tabindex="-1">There are 4
possible values for command byte 1, we use the value 1 to freeze the
screen image and 0 to unfreeze it when the process is finished. <span>As we see in the tags we have defined in sgb.z80.</span></span><br />
<br />
<script src="//pastebin.com/embed_js/KcrnCtUV"></script><br />
<span id="result_box" lang="en" tabindex="-1">And once the digression is finished, this is the data transfer routine. <span>We will place it in main.asm.</span></span></div>
<br />
<script src="//pastebin.com/embed_js/t5hPy62e"></script>
<br />
<div style="text-align: justify;">
<span id="result_box" lang="en" tabindex="-1">As we can see, we have an additional routine called "parsesgbbordertiles". <span>This
routine allows us to save memory in case the data we want to copy is 2bpp, since it will fill with zeroes the bit planes 3
and 4 (which we do not use).</span> <span>In our case, being 4bpp tiles, we do not make use of it.</span></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span id="result_box" lang="en" tabindex="-1"><span>And
finally, using the routines we have developed so far, this would be the
description of the main initialization routine of the Super Game Boy:</span></span></div>
<ol style="text-align: justify;">
<li><span id="result_box" lang="en" tabindex="-1"><span>we check if we are in a Super Game Boy, if we are not, we return and the routine ends;</span></span></li>
<li><span id="result_box" lang="en" tabindex="-1"><span>we freeze the LCD display of the Game Boy throughout the process;</span></span></li>
<li><span id="result_box" lang="en" tabindex="-1"><span>we send the initialization packets recommended by the documentation</span></span>;</li>
<li><span id="result_box" lang="en" tabindex="-1">we copy the 256 tiles we will use in the frame to the SNES RAM. <span>In two batches of 128;</span></span></li>
<li><span class="short_text" id="result_box" lang="en" tabindex="-1"><span>we copy the frame information to the SNES RAM;</span></span></li>
<li><span id="result_box" lang="en" tabindex="-1"><span>we copy the information of the game palettes to the SNES RAM;</span></span></li>
<li><span id="result_box" lang="en" tabindex="-1"><span>we assign the palette previously copied as a palette to be used in the game</span></span>;</li>
<li><span id="result_box" lang="en" tabindex="-1"><span>we clear the Game Boy VRAM and unfreeze the Game Boy LCD display to complete the process</span></span>.</li>
</ol>
<div style="text-align: justify;">
<span class="short_text" id="result_box" lang="en" tabindex="-1"><span>We add this code to main.asm</span></span> (<a href="https://drive.google.com/file/d/0B5EtmvQp4iqoUl9rbTluV3llelE/view?usp=drive_link&resourcekey=0-o0LRTvq8uB_KuFh-PEtXSg">FILE DOWNLOAD</a>).</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<script src="//pastebin.com/embed_js/z1WyNjnq"></script></div>
<div style="text-align: justify;">
<br />
<span id="result_box" lang="en" tabindex="-1"><span>If we now execute the assemble.bat file of the project we will have the ROM with the frame and the customized palettes as a result.</span></span><br />
<br />
<div style="text-align: center;">
<a href="https://drive.google.com/file/d/0B5EtmvQp4iqoc0dHRTRJS09GNjQ/view?usp=drive_link&resourcekey=0-QmWMNwEklAmnaTmUgaitkQ"><span style="font-size: large;">COMPLETE PROJECT DOWNLOAD</span></a></div>
<br />
<br />
<span id="result_box" lang="en" tabindex="-1">I terminate the explanation of this simple prototype. Naturally, many features of the Super Game Boy remain to be applied. <span>But
I hope this article serves as a starting point for people who have been
encouraged to develop for the Game Boy but have not found any minimally
guided development resources for Super Game Boy.</span></span><br />
<br />
<span id="result_box" lang="en" tabindex="-1"><span>Any note or critic of any kind will be welcome, and any part of the post is subject to change if necessary.</span></span><br />
<br />
<span id="result_box" lang="en" tabindex="-1"><span class="alt-edited">So I can only give encouragement.</span> <span>Now you have to implement that Super Game Boy frame that you have always wanted to design.</span></span></div>
<br /></div>
</div>
</div>
</div>
</div>
</div>
</div>
Imanoleahttp://www.blogger.com/profile/03989722316939496203noreply@blogger.com6tag:blogger.com,1999:blog-2099766654099311467.post-17521871596116405382016-12-28T00:27:00.017+01:002023-08-28T20:49:59.714+02:00Games aside #1: Desarrollo para Super Game Boy (paso a paso)<div style="text-align: justify;">
A lo largo de esta entrada vamos a aprender a implementar alguna de las funcionalidades que ofrece el Super Game Boy, concretamente las que aprovecha la recientemente publicada <a href="https://imanoleasgames.blogspot.com/2016/06/rocket-man-demo.html">ROM mejorada para Super Game Boy</a> de la demo de Rocket Man. Demo expuesta como producción local en el certamen internacional de videojuegos independientes <a href="http://www.azplaybilbao.com/">AzPlay</a> celebrado el pasado noviembre en Bilbao.</div>
<div style="text-align: justify;">
<span style="font-size: small;"><br /></span></div>
<div style="text-align: justify;">
Antes de comenzar me gustaría aclarar una serie de puntos:</div>
<ol style="text-align: justify;">
<li>el programa que se va a elaborar está programado en ensamblador y hace uso de <a href="https://github.com/bentley/rgbds">RGBDS</a> para la creación de la ROM;</li>
<li style="text-align: justify;">esta publicación no cubre las bases del desarrollo para Game Boy en ensamblador, pero
tampoco requiere un conocimiento avanzado sobre el tema. Puede funcionar como lección adicional a los numerosos tutoriales que existen en la red al respecto (recomendación personal en castellano, <a href="http://wiki.ladecadence.net/doku.php?id=tutorial_de_ensamblador">http://wiki.ladecadence.net/doku.php?id=tutorial_de_ensamblador</a>);</li>
<li style="text-align: justify;">de acuerdo al segundo punto, se parte de un programa base en el que se trabaja la implementación de funciones adicionales relacionadas con el Super Game Boy.</li>
</ol>
<div style="text-align: justify;">
En esta entrada se va a cubrir el uso de las siguientes características exclusivas del Super Game Boy:</div>
<ul style="text-align: justify;">
<li>despliegue de un marco personalizado;</li>
<li>paletas personalizadas para los gráficos del juego.</li>
</ul>
<div style="text-align: justify;">
Dando como resultado del aprendizaje la siguiente ROM de Game Boy. </div>
<div style="text-align: justify;">
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfR7SfwFwhDOVt-dcbrhVO3yTcq0KcGfeIr-0yvCTYoRnp9pe35EJRqv5vTtdRjBm0IgtFNA_v5AATzqihmEtRG0rs-ZPTGoTZP-5-MOv8URQmhbCj5hu7RmEgVpiOKvuLi-rOmABbmKQ/s1600/sgbdev.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="280" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfR7SfwFwhDOVt-dcbrhVO3yTcq0KcGfeIr-0yvCTYoRnp9pe35EJRqv5vTtdRjBm0IgtFNA_v5AATzqihmEtRG0rs-ZPTGoTZP-5-MOv8URQmhbCj5hu7RmEgVpiOKvuLi-rOmABbmKQ/s320/sgbdev.png" width="320" /></a></div>
</div>
<div style="text-align: center;">
<span style="font-size: x-small;">Visualización de la ROM en una Super Game Boy</span><br />
<span style="font-size: large;"> <a href="https://drive.google.com/file/d/0B5EtmvQp4iqoT3BJX1dXWFdFSTA/view?usp=drive_link&resourcekey=0-wAHSK8uTGT_kE7DY69GeiA">DESCARGA DE LA ROM</a> </span></div>
<br />
<div style="text-align: justify;">
Primero deberíamos hablar sobre qué es el Super Game Boy. Se trata, según el <i><a href="https://drive.google.com/file/d/0B5EtmvQp4iqoTTJWX3dEekdaVEE/view?usp=drive_link&resourcekey=0-CgdC8gfVkZwJ655WmmO4nA">Game Boy Programming Manual</a></i> (<i>pág 124</i>), de un dispositivo que permite disfrutar del software de Game Boy en una pantalla de televisión. Este software (contenido en el cartucho de Game Boy) puede conectarse al Super Game Boy, el cual opera en una Super Nintendo.</div>
<div style="text-align: justify;">
<span style="font-size: small;"><br /></span></div>
<div style="text-align: justify;">
Sobre esta definición cabe resaltar la última parte, el Super Game Boy opera en una Super Nintendo. Este cartucho es una réplica del hardware de la Game Boy capaz de comunicarse con la SNES, nos ayuda a informar a la sobremesa de las operaciones que queremos realizar y a enviarle los datos necesarios, pero es en última instancia su hardware y no el nuestro (el del Super Game Boy) el que se encarga de procesar y aplicar la funcionalidades exclusivas que nos ofrece esta tecnología. Es decir, los gráficos del marco por ejemplo, obedecen las limitaciones de la SNES y no de la Game Boy.<br />
<br />
<h2>
<span style="font-size: large;">Preparativos</span></h2>
</div>
<div style="text-align: justify;">
Dicho esto, pasamos a la preparación del equipo donde vayamos a desarrollar. Esta sería una lista de elementos que deberíamos tener listos en nuestro PC con Windows:</div>
<ol style="text-align: justify;">
<li>editor de texto/código para la edición del programa (recomendación personal, <a href="https://code.visualstudio.com/">Visual Studio Code</a> y la extensión <a href="https://marketplace.visualstudio.com/items?itemName=Imanolea.z80-asm">Z80 Assembly</a>);</li>
<li><a href="https://github.com/bentley/rgbds">RGBDS</a> correctamente configurado como variable de entorno;</li>
<li><a href="http://www.devrs.com/gb/hmgd/gbtd.html">Game Boy Tile Designer</a> y <a href="http://www.devrs.com/gb/hmgd/gbmb.html">Game Boy Map Builder</a> para la edición de gráficos y mapas respectivamente;</li>
<li>a pesar de que el programa de esta publicación está testeado en un Super Game Boy real, se recomienda disponer de la tecnología necesaria para ejecutar la ROM resultante en el hardware final. En su defecto, emuladores como <a href="http://bgb.bircd.org/">BGB</a> o <a href="http://www.emulator-zone.com/doc.php/snes/bsnes.html">bsnes</a> pueden servir para probar los desarrollos que se hagan con este dispositivo en mente, pero no garantizan una emulación perfecta.</li>
</ol>
<div style="text-align: justify;">
Pues bien, toca ponerse manos a la obra. Como esta publicación trata sobre el desarrollo para Super Game Boy y no sobre el desarrollo para Game Boy vamos a partir de un proyecto base cuya ROM ofrece el siguiente resultado.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0ART4xjWC1veH9rLgqDimoBibbH4lsV2eIrI1gkBJ4EkaU0UdYvor6M_SKvh1rB-8l8kChT4DeFs-_rxoKYRxnvASXYrsq3yax7I15RSJqm4wfCfkeBwJma0iGfY6mYKU7SN6urZSzZU/s1600/sgbdev_base.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="288" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0ART4xjWC1veH9rLgqDimoBibbH4lsV2eIrI1gkBJ4EkaU0UdYvor6M_SKvh1rB-8l8kChT4DeFs-_rxoKYRxnvASXYrsq3yax7I15RSJqm4wfCfkeBwJma0iGfY6mYKU7SN6urZSzZU/s320/sgbdev_base.png" width="320" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">Una pantalla de título estática</span></div>
<div style="text-align: center;">
<span style="font-size: large;"><a href="https://drive.google.com/file/d/0B5EtmvQp4iqoUzJZZGx0MDIyb1U/view?usp=drive_link&resourcekey=0-zkv2n6PG0BipJCop4qzIQw">DESCARGA DEL PROYECTO</a> </span></div>
<br />
Este es el código del fichero principal de este proyecto plantilla.<br />
<br />
<div style="text-align: justify;">
<script src="//pastebin.com/embed_js/DsgN3Lat"></script></div>
<br />
Durante el desarrollo va a ser importante tener cerca cierta documentación a mano. En mi opinión, estos serían los textos que condensan todo lo que se necesita saber cuando se trata de programar para Super Game Boy:<br />
<ul>
<li><i><a href="https://drive.google.com/file/d/0B5EtmvQp4iqoTTJWX3dEekdaVEE/view?usp=drive_link&resourcekey=0-CgdC8gfVkZwJ655WmmO4nA"><span style="font-size: small;">Game Boy Programming Manual</span></a></i>;</li>
<li><span style="font-size: small;"><i>SGB Functions - GbdevWiki (<a href="http://gbdev.gg8.se/wiki/articles/SGB_Functions">http://gbdev.gg8.se/wiki/articles/SGB_Functions</a>)</i>.</span></li>
</ul>
Cada vez que dé información sobre el Super Game Boy procuraré complementarla con la fuente de dicha información, indicando en qué parte de estos dos documentos se encuentra.<br />
<br />
<h2>
<span style="font-size: large;">Elaboración de gráficos</span></h2>
Empezaremos diseñando libremente el marco de Super Game Boy que queremos aplicar. Eso sí, teniendo en cuenta las siguientes limitaciones:</div>
<div style="text-align: justify;">
<ol>
<li>la resolución del marco debe cuadrar con la resolución de la SNES, es decir, 256 píxeles de ancho por 224 píxeles de alto;</li>
<li>debemos dejar un espacio en blanco de 160 por 144 píxeles en la parte central, que es donde se mostrará la pantalla de la Game Boy;</li>
<li>la SNES dispone de 8 paletas de 16 colores RGB de 15 bit (<i>SGB Functions > Available SNES Palettes</i>). Las cuatro primeras (0-3) se usan para colorear los propios gráficos de la Game Boy y las cuatro últimas (4-7) para el marco. En el apartado Paletas del marco explico con más detalle esta limitación;</li>
<li>no podemos usar más de 256 tiles de 8 por 8 píxeles a la hora de conformar el marco (los tiles de la SNES son de 8x8 y disponemos de un byte para direccionarlos. Lo bueno es que estos tiles pueden voltearse horizontal y verticalmente. </li>
</ol>
<br />
<h2>
Paletas del marco</h2>
Como hemos comentado tenemos ha nuestra disposición 4 paletas de 16 colores para el marco. Aunque no exactamente, según la documentación oficial tenemos de la 4-6 (<i>Game Boy Programming Manual > pág 162</i>), es decir, 3 paletas. De todas formas también podemos hacer uso de la 7. Eso sí, algunos emuladores no reconocerán esta última paleta correctamente.<br />
<br />
Color RGB de 15 bit, ¿qué implica esto? Pues que tenemos 5 bits para indicar el nivel de rojo, 5 para el verde y 5 para el azul. Es decir, una precisión de 0-31 para definir la intensidad de cada uno de los colores. Si tenemos un color RGB de 24 bit (el formato predominante) que queremos usar en alguna de las paletas tendriamos que redondear el valor de 0 a 255 que tenemos por color al equivalente entre 0 y 31.<br />
<br />
Hemos dicho 16 colores, hay que matizarlo: ¡el color 0 es compartido (<i>SGB Functions > Color 0 Restriction</i>)! Esto significa que si el color 0 de la última paleta que asignemos es rojo, el color 0 del resto de gráficos pasará a ser el rojo. Y tenemos 16 colores sólo en el caso de que queramos gastar la memoria necesaria para almacenar gráficos 4bpp (4 bits por pixel) en la Game Boy. Si con 2bpp nos basta tenemos entonces cuatro colores por paleta con el color 0 compartido, pero los gráficos nos ocuparán la mitad de memoria.<br />
<br />
Hay muchos juegos que aceptan la limitación de cuatro colores por paleta en el marco mostrando el color 0 para ahorrar memoria. Como por ejemplo ocurre con el marco del Pokémon Azul.<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqZSHiQ2PGTt0yV7E3bdw2Ph-AO0gTgpmVncZQZWI2g9HUCSPlj2eduR6QALMxo9xL-XedHc4fRS4PNUc7aY98XT-TS-IewP7j89uFpXl4piFWjI2LOuc5pRNnrN2owvXfyoCrUbDBy_w/s1600/pokemonazul.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="280" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqZSHiQ2PGTt0yV7E3bdw2Ph-AO0gTgpmVncZQZWI2g9HUCSPlj2eduR6QALMxo9xL-XedHc4fRS4PNUc7aY98XT-TS-IewP7j89uFpXl4piFWjI2LOuc5pRNnrN2owvXfyoCrUbDBy_w/s320/pokemonazul.png" width="320" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">Comparando los dos cuadrados rojos vemos que el marco muestra el color 0 compartido con el resto de paletas. Usando además cuatro colores por tile (2bpp)</span><br />
<div style="text-align: left;">
<span style="font-size: x-small;"><br /></span></div>
</div>
<div style="text-align: left;">
<h2>
Nuestro marco</h2>
</div>
Este es nuestro marco.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJd7tvcULAAWamoegu1qAPyYlc15QWRBwCAShOZ4qDSh2rg5lWliKHA2FM-xGso1YATscDZWcmGgoyPJA44-aZb7FV7P8X2BRGqBzMbZ1-14mfflcnEGvLY-WBvGFImBsGDWkby-5Qwy4/s1600/frame.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="350" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJd7tvcULAAWamoegu1qAPyYlc15QWRBwCAShOZ4qDSh2rg5lWliKHA2FM-xGso1YATscDZWcmGgoyPJA44-aZb7FV7P8X2BRGqBzMbZ1-14mfflcnEGvLY-WBvGFImBsGDWkby-5Qwy4/s400/frame.png" width="400" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">Marco de 256 por 224 píxeles</span> </div>
<br />
Estos nuestros tiles.<br />
<br />
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-kCxxy9m3SS-aOezG5iJhqHUnx45443xhVK69lTU4REtSYmYuZ-TFEt6hlsvSvxcQtt31jJzgZtjm_VvuNNJCyOR68-BwxXC_GcVPNA9znf3SK4ChCFsJsHSYty_OVPI7qFImyYyWG2I/s1600/tiles.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-kCxxy9m3SS-aOezG5iJhqHUnx45443xhVK69lTU4REtSYmYuZ-TFEt6hlsvSvxcQtt31jJzgZtjm_VvuNNJCyOR68-BwxXC_GcVPNA9znf3SK4ChCFsJsHSYty_OVPI7qFImyYyWG2I/s400/tiles.png" width="228" /></a> </div>
<div style="text-align: center;">
<span style="font-size: x-small;">176 tiles (incluyendo el tile nulo) de los 256 disponibles </span></div>
<br />
Y estas nuestras paletas.<br />
<br />
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-W_oL44qtSG1Vvd49KltlFV3Ue91E_7p0ADLMcKzDe9WHbDgyu9NE4xj2QWJkoEdxhq2DJLv7ns5Wkm7yi5h2JZsQFwhHwE3sJwK43-4SNLVKHVbQxNUinygZXN5Sj0QJGQhsJfpqq6A/s1600/palettes.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="70" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-W_oL44qtSG1Vvd49KltlFV3Ue91E_7p0ADLMcKzDe9WHbDgyu9NE4xj2QWJkoEdxhq2DJLv7ns5Wkm7yi5h2JZsQFwhHwE3sJwK43-4SNLVKHVbQxNUinygZXN5Sj0QJGQhsJfpqq6A/s400/palettes.png" width="400" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">Paletas 4-6 usadas para representar los colores de cada uno de los tiles</span> </div>
<br />
Tres paletas de 16 colores (4bpp), el color 0 (primera columna) no lo usamos para no tener que compartirlo con las paletas que se van a usar en los gráficos de Game Boy. Por las características del desarrollo, esta es la distribución de colores que ha quedado en las tres paletas. Bien podría haberse usado una sola, ya que guardan entre ellas bastantes colores en común.<br />
<br />
Y ahora, es momento de convertir estas especificaciones en datos que añadir a nuestro programa.<br />
<br />
<h2>
Archivo de tiles</h2>
Los datos gráficos de los tiles los crearemos con <a href="http://www.devrs.com/gb/hmgd/gbtd.html">Game Boy Tile Designer</a>. En nuestro marco alguna de las paletas usa más de 4 colores así que nuestros gráficos deberán ser 4bpp.<br />
<br />
En el caso de que los gráficos sean 2bpp sencillamente dibujamos los tiles con el editor teniendo en cuenta que los colores que eligamos para el valor 0, 1, 2, y 3 se corresponderán con los colores 0, 1, 2 y 3 de la paleta que tengamos pensada para ese tile.<br />
<br />
<div style="text-align: center;">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6YV8GLz_NPcXotgns4Hj5XzFN2jqcv9R7FtxVtVAppY1YDXg5QAu25-FMFDtXODzOAqfZp8deJhAQ1wrAlwHBdR6UgIA6np9ENztTuZePisKE5zpmrIvpnrYpeCp06cqw34R3eMvHces/s1600/2bpp.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6YV8GLz_NPcXotgns4Hj5XzFN2jqcv9R7FtxVtVAppY1YDXg5QAu25-FMFDtXODzOAqfZp8deJhAQ1wrAlwHBdR6UgIA6np9ENztTuZePisKE5zpmrIvpnrYpeCp06cqw34R3eMvHces/s1600/2bpp.png" width="512" /></a></div>
</div>
<div style="text-align: center;">
<span style="font-size: x-small;">Izquierda: tile en <a href="http://www.devrs.com/gb/hmgd/gbtd.html">Game Boy Tile Designer</a>; centro: paleta especificada para el tile; derecha: visualización del tile en el Super Game Boy</span> </div>
<br />
Los gráficos 4bpp de la SNES también podemos crearlos de manera sencilla usando el mismo programa: dibujando dos tiles consecutivos de Game Boy por cada tile de Super. El primero para los <i>bit planes </i>1 y 2, y el segundo para los número 3 y 4.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDVXT1BsjafpgQG8x-9jhJ0nRcg9IgbF7AAGoklxiA73RQncdlsh9SAHJQ30ununTy2dltW9mMLW20RxZDB4qRS2m7N3GIWzCfyyvL0rcukHvKhrAq_zw6IGo8ScmX08DyXUHvQedvmg4/s1600/4bpp.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDVXT1BsjafpgQG8x-9jhJ0nRcg9IgbF7AAGoklxiA73RQncdlsh9SAHJQ30ununTy2dltW9mMLW20RxZDB4qRS2m7N3GIWzCfyyvL0rcukHvKhrAq_zw6IGo8ScmX08DyXUHvQedvmg4/s1600/4bpp.png" width="512" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">Podemos combinar dos píxeles de Game Boy (2 bits) para crear un pixel de SNES (4 bits)</span></div>
<br />
Aunque usemos gráficos 4bpp también debemos tener un archivo .gbr que dedique un sólo tile de Game Boy por tile de SNES. Y lo usaremos al elaborar el mapa del marco con <a href="http://www.devrs.com/gb/hmgd/gbmb.html">Game Boy Map Builder</a>, de esta forma referenciaremos el número de tile como lo haría la SNES y no la Game Boy.<br />
<br />
El resultado de la elaboración de estos tileset en <a href="http://www.devrs.com/gb/hmgd/gbtd.html">Game Boy Tile Designer</a> es el siguiente: el tileset que almacenará los gráficos a usar en el marco (<a href="https://drive.google.com/file/d/0B5EtmvQp4iqoVlNELU9tb2NnZDA/view?usp=drive_link&resourcekey=0-vlFEQU4CoVLEepRfRsUWmg">DESCARGAR EL ARCHIVO</a>) y el tileset cuya única función será contener un índice de los tiles para mapearlos posteriormente (<a href="https://drive.google.com/file/d/0B5EtmvQp4iqoejBtODhwQTB0dUE/view?usp=drive_link&resourcekey=0-9OzbdkwgeF0P1sUQNIDXFw">DESCARGAR EL ARCHIVO</a>). Dentro del proyecto, ubicaremos estos dos archivos en res/tiles/.<br />
<br />
Y con la siguiente configuración, exportamos el tileset de 4bpp para obtener el archivo de datos necesario para el proyecto. Borramos la declaración de sección y las etiquetas generadas automáticamente y ubicamos el archivo resultante en dev/data/tiles/ como sgb_tileset.z80 (<a href="https://drive.google.com/file/d/0B5EtmvQp4iqoYjBhWHc2cDRJcFE/view?usp=drive_link&resourcekey=0-rvD4B1CcY3oA_MnhsRNGDA">DESCARGAR EL ARCHIVO</a>).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh80c24irHUjXo9f6Tv1avuU9-BLdGavQT4Oz319PcS_BuPUvwZKQOMsTVe7E59nmhiT5z3vR0k18lPXl_jw2qzYvMMf7mcVgVpUXjh8-Eu4KzOuYjzBsQqfMab45_iJ3E2QQQveP5f93E/s1600/exportconfig.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh80c24irHUjXo9f6Tv1avuU9-BLdGavQT4Oz319PcS_BuPUvwZKQOMsTVe7E59nmhiT5z3vR0k18lPXl_jw2qzYvMMf7mcVgVpUXjh8-Eu4KzOuYjzBsQqfMab45_iJ3E2QQQveP5f93E/s1600/exportconfig.png" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">Generamos un archivo .z80 compatible con RGBDS</span></div>
<div style="text-align: center;">
<br /></div>
<h2>
Archivo de mapa</h2>
Ahora, con <a href="http://www.devrs.com/gb/hmgd/gbmb.html">Game Boy Map Builder</a>, construiremos el marco. Debemos asociarlo al archivo .gbr del tileset con los índices correctos, el que utiliza un sólo tile de Game Boy por tile de Super. Recordemos además que las dimensiones del marco son 256 por 224 píxeles, lo que significa 32 por 28 tiles. Así que una vez abramos el programa nos dirigimos a "File > Map properties..." y nos encargamos de cuadrar dimensiones y tileset.<br />
<span style="font-size: small;"></span><br />
<div class="separator" style="clear: both; text-align: center;">
<span style="font-size: small;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUy2J2t3x5uuc2_z0kh8ieOQiM8gnyJwaa48UPKP0phAxAxUbd4-hEVKR8G8bHB7lJIzj4x1KEU7vWNdFK8sFqDvdzOx1Fkz5WM2ydarpJeNV4AyN7ic7GXs0EshfIgrO7jwczYglYcLs/s1600/mapproperties.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUy2J2t3x5uuc2_z0kh8ieOQiM8gnyJwaa48UPKP0phAxAxUbd4-hEVKR8G8bHB7lJIzj4x1KEU7vWNdFK8sFqDvdzOx1Fkz5WM2ydarpJeNV4AyN7ic7GXs0EshfIgrO7jwczYglYcLs/s1600/mapproperties.png" /></a></span></div>
<div style="text-align: center;">
<span style="font-size: small;"> <span style="font-size: x-small;">El tileset que aquí usemos sólo sirve como referencia visual a la hora de mapear los tiles</span></span></div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: justify;">
Como comentaba anteriormente, los tiles de la SNES se pueden voltear tanto horizontal (X Flip) como verticalmente (Y Flip). Adicionalmente cada uno de los tiles va a estar asociado a una de las paletas que hayamos especificado. Por eso necesitamos definir atributos adicionales para cada tile que coloquemos en nuestro mapa. Podemos hacer esto en "File > Location properties...".</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJ_OxPdXo5x48GP0ooVWlWD_um8vKIe8aEthI8-YLCRVEwMR7WJMuxu6pgyC9aW9CbJ1sag4ghLgj4Brdi4DeuqmxvuEIDz87_fcBV31Tlw5-QLI-DIvWJ-v4QY-5pKVyCBgB5mPxCXpQ/s1600/locationproperties.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJ_OxPdXo5x48GP0ooVWlWD_um8vKIe8aEthI8-YLCRVEwMR7WJMuxu6pgyC9aW9CbJ1sag4ghLgj4Brdi4DeuqmxvuEIDz87_fcBV31Tlw5-QLI-DIvWJ-v4QY-5pKVyCBgB5mPxCXpQ/s1600/locationproperties.png" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">No definimos el volteo vertical (Y Flip) porque no es usado en nuestro marco</span></div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: justify;">
Como veremos a continuación el volteo se define con un único bit (1 volteado, 0 no volteado) y la paleta con 2 (rango de 0 a 3 que se correponde respectivamente con las paletas de la 4 a la 7), estos serán los 2 bit más bajos de los 3 que se asignan posteriormente a la paleta. Al tercer bit, el más alto, le daremos siempre el valor de 1. Esto nos da un rango de valores de 4 a 7 real al exportar.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Ahora mapeamos los tiles del marco, y definimos sus <i>location properties </i>a través de los campos disponibles en la fila inferior del editor.</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEix6kmVSYMH6l-urOi4hhsWudL23qhHuS17VA8r3VLZzoCKfy9tBFiLHJbqfYVmnpmWFb4rHvMKqrj_YrQOkNjV6OlxQAEeVZm6up6kapcGw12wbKPh_31WwZxKCnCn759IALAq3KnDftg/s1600/bordermap.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEix6kmVSYMH6l-urOi4hhsWudL23qhHuS17VA8r3VLZzoCKfy9tBFiLHJbqfYVmnpmWFb4rHvMKqrj_YrQOkNjV6OlxQAEeVZm6up6kapcGw12wbKPh_31WwZxKCnCn759IALAq3KnDftg/s1600/bordermap.png" width="512" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">Recordemos que debemos dejar un espacio de tiles nulos en la ubicación de la pantalla de la Game Boy</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Como resultado, tenemos un archivo .gbm con el diseño del mapa que conformará el marco (<a href="https://drive.google.com/file/d/0B5EtmvQp4iqoc2ZQc3FSVDZUM3c/view?usp=drive_link&resourcekey=0-fKRxLcDHSLZM-Dt2BF4MPQ">DESCARGAR EL ARCHIVO</a>), lo situamos en res/maps/. Como apunte, aclarar que lo primero que debemos hacer al abrir el mapa en Game Boy Map Builder es referenciar el tileset de los índices a través de "File > Map properties...".</div>
<br />
Ahora vamos a generar el archivo de datos relativo al mapa a través de "File > Export to...". Vamos a asegurarnos de que cumplimos con la especificación sobre el formato del mapa (<i>SGB Functions > SGB Command 14h - PCT_TRN</i>). En las opciones de la exportación incluiremos las <i>location properties</i> que hemos definido anteriormente. Esta sería la especificación oficial respecto a nuestra configuración de exportación.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmwj1Zn1VFJOPQCdkRxlfp_RO1EUUF6iJUMcxWOgZCq8NDPdiufixW7kKlC3WlxSGk44mV-b3e5uct1WYZDz4ra12NOX6oYyA6ks4Sugkv8DrSy6wQH2AnpEHuUGpvtCVm9aGLKVuUtYE/s1600/bkmapentry.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmwj1Zn1VFJOPQCdkRxlfp_RO1EUUF6iJUMcxWOgZCq8NDPdiufixW7kKlC3WlxSGk44mV-b3e5uct1WYZDz4ra12NOX6oYyA6ks4Sugkv8DrSy6wQH2AnpEHuUGpvtCVm9aGLKVuUtYE/s1600/bkmapentry.png" width="512" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">Especificación oficial del formato de los tiles del mapa del marco</span></div>
<div style="text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-size: x-small;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjH3kZghZq1ToCoZrVjJ75yFmZAB7pAK-pLJ03dBhOLAONgmAkDle5FRCxWItYs06cihKRw7rEYGSTgKwvUKqfPpeh7q5XkXVjLb_imPo4NusNrKFqhP54-4ZTpb-oOdsWl8QCBrr49x2A/s1600/mapexportconfig.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjH3kZghZq1ToCoZrVjJ75yFmZAB7pAK-pLJ03dBhOLAONgmAkDle5FRCxWItYs06cihKRw7rEYGSTgKwvUKqfPpeh7q5XkXVjLb_imPo4NusNrKFqhP54-4ZTpb-oOdsWl8QCBrr49x2A/s1600/mapexportconfig.png" /></a></span></div>
<div style="text-align: center;">
<span style="font-size: x-small;">En el caso de la propiedad Y Flip, la ignoramos ocupando su lugar con un 0 </span></div>
<div style="text-align: center;">
<br />
<div style="text-align: justify;">
<div style="text-align: justify;">
Una vez exportado, borramos la declaración de sección y las etiquetas del archivo resultante y lo ubicamos en dev/data/maps/ (<a href="https://drive.google.com/file/d/0B5EtmvQp4iqoMUNoZ1JIUVY5S2c/view?usp=drive_link&resourcekey=0-Rifhjhkh1wnhzCIol4C2Tw">DESCARGAR EL ARCHIVO</a>).<span style="font-size: x-small;"> </span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Ya tenemos todos los archivos gráficos listos, sólo faltan los datos de las paletas. Para ello vamos a crear ahora el archivo sgb.z80, que ubicaremos en dev/data/. Aquí vamos a ubicar las definiciones de los paquetes que enviaremos a la SNES y en este caso también la macro del RGB de 15 bits del que se servirán los colores de nuestras paletas.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<script src="//pastebin.com/embed_js/5CtdshEY"></script>
</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: left;">
<div style="text-align: justify;">
Los tres parámetros de la macro se corresponden respectivamente con el valor de rojo, de verde y de azul que queramos darle a cada color. Pues bien, ahora toca especificar las paletas en base a esta macro.<br />
<br />
Debemos colocar las paletas a continuación de los datos del mapa (<i>SGB Functions > SGB Command 14h - PCT_TRN</i>), así que crearemos un archivo en dev/data/maps que se llame sgborder.z80 (<a href="https://drive.google.com/file/d/0B5EtmvQp4iqoSmhCcXJEN1l2Z1k/view?usp=drive_link&resourcekey=0-qNsJAd_6HkLdYqLNvtUPUg">DESCARGAR EL ARCHIVO</a>), allí cuadraremos nuestras paletas con la especificación.<br />
<span style="font-size: small;"> </span><br />
<div class="separator" style="clear: both; text-align: center;">
<span style="font-size: small;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzd4cYy4NegO5l76jII7ZU4oeKKbAHG6DJDd8XCuf9-OdHiMVdd6IbeXeHSL56D1LB7UpgfFCY-Zu-OOrIr6nCCzRVpUu2a9q8_gdzzfm8FtLTx8kwW6yE1SXHcKljkiAPtqsJyN3Fh0c/s1600/bkgmapdata.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzd4cYy4NegO5l76jII7ZU4oeKKbAHG6DJDd8XCuf9-OdHiMVdd6IbeXeHSL56D1LB7UpgfFCY-Zu-OOrIr6nCCzRVpUu2a9q8_gdzzfm8FtLTx8kwW6yE1SXHcKljkiAPtqsJyN3Fh0c/s1600/bkgmapdata.PNG" width="512" /></a></span></div>
<div style="text-align: center;">
<span style="font-size: small;"><span style="font-size: x-small;">El mapa debe ser de 32x32 tiles pero las últimas 4 filas no entran en la pantalla y son innecesarias</span></span></div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
<span style="font-size: small;"><span style="font-size: x-small;"> </span></span><span style="font-size: small;"><span style="font-size: x-small;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-W_oL44qtSG1Vvd49KltlFV3Ue91E_7p0ADLMcKzDe9WHbDgyu9NE4xj2QWJkoEdxhq2DJLv7ns5Wkm7yi5h2JZsQFwhHwE3sJwK43-4SNLVKHVbQxNUinygZXN5Sj0QJGQhsJfpqq6A/s1600/palettes.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-W_oL44qtSG1Vvd49KltlFV3Ue91E_7p0ADLMcKzDe9WHbDgyu9NE4xj2QWJkoEdxhq2DJLv7ns5Wkm7yi5h2JZsQFwhHwE3sJwK43-4SNLVKHVbQxNUinygZXN5Sj0QJGQhsJfpqq6A/s1600/palettes.png" /> </a></span></span></div>
<div style="text-align: center;">
<span style="font-size: x-small;">Recordamos la especificación de nuestras paletas</span><br />
<br />
<script src="//pastebin.com/embed_js/QCWike2t"></script>
<span style="font-size: small;"><span style="font-size: x-small;">El primer color de cada paleta (color 0) está especificado pero no llega a usarse </span></span><br />
<div style="text-align: left;">
<div style="text-align: justify;">
<h2>
Paletas del juego</h2>
Por último vamos a añadir a sgb.z80 la declaración de la paleta que usaremos para los gráficos del propio juego. Recordemos que mientras las paletas de la 4-7 se usan para el marco, las de la 0-3 se usan para los gráficos del juego. Los gráficos monocromos de la Game Boy tienen una limitación de 4 colores así que sólo podremos usar 4 colores en esta paleta.</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyHtnYLp-PBbHWcS8F_uL3CqoAMFxFZCumThEBL4kAV4iZ5kFdhweZ5u5kWrFuU-6OC4a2RfuXcu6Yx8XnX9BuL394nhk3cdrejgS7_QkhZ4vDGhBAZc02GPuIMXaySbA3HPuwb2AvZII/s1600/gamepalettes.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyHtnYLp-PBbHWcS8F_uL3CqoAMFxFZCumThEBL4kAV4iZ5kFdhweZ5u5kWrFuU-6OC4a2RfuXcu6Yx8XnX9BuL394nhk3cdrejgS7_QkhZ4vDGhBAZc02GPuIMXaySbA3HPuwb2AvZII/s1600/gamepalettes.png" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">Sólo usaremos una de las cuatro paletas asignables al juego de Game Boy</span></div>
<div style="text-align: center;">
<br />
<script src="//pastebin.com/embed_js/Wj08cWh2"></script></div>
<div style="text-align: center;">
<span style="font-size: x-small;">El color 0 que definamos debería ser el que queramos compartir con el resto de paletas </span></div>
<br />
<div style="text-align: justify;">
Pues ya tenemos especificados todos los archivos gráficos necesarios, llegó el momento de añadirlos al banco de memoria que tenemos declarado en main.asm.</div>
<br />
<script src="//pastebin.com/embed_js/aEXpUi7z"></script>
<span style="font-size: large;"> </span><br />
<h2>
<span style="font-size: large;">Programación de la lógica</span></h2>
<br />
<h2>
Definiciones auxiliares</h2>
<div style="text-align: justify;">
Existen dos formas de enviar información a la Super (<i>Game Boy Programming Manual > pág 127</i>), a través de los registros P14 y P15 y a través la propia VRAM de la Game Boy (transferencia de VRAM). Ambas implican el uso de comandos. Así que empezaremos definiendo en nuestro archivo sgb.z80 las macros de los comandos que vamos a utilizar (tenemos una definición de lo que hace cada comando en <i>Game Boy Programming Manual > pág 132</i> y <i>SGB Functions > SGB Command Summary</i>):
</div>
<ol>
<li style="text-align: justify;">MLT_REQ, hace una petición del modo multijugador, se usará para detectar si el cartucho se está ejecutando en un Super Game Boy;</li>
<li style="text-align: justify;">CHR_TRN, lo usaremos para copiar los tiles del marco a la RAM de la SNES (con una transferencia de VRAM);</li>
<li style="text-align: justify;">PCT_TRN, lo usaremos para copiar el mapa del marco a la RAM de la SNES (con una transferencia de VRAM);</li>
<li style="text-align: justify;">PAL_SET, asignará la paleta que tenemos definida para los gráficos del juego;</li>
<li style="text-align: justify;">PAL_TRN, copiará la paleta que tenemos definida para los gráficos del juego a la RAM de la SNES (con una transferencia de VRAM);</li>
<li style="text-align: justify;">MASK_EN, congelará la pantalla durante los procesos de comunicación con el Super Game Boy, y la descongelará al terminar;</li>
<li style="text-align: justify;">Por último definiremos ocho paquetes de datos que enviaremos para inicializar la comunicación tal y como se recomienda en la documentación oficial (<i>Game Boy Programming Manual > pág 178</i>).</li>
</ol>
<ol>
</ol>
<div style="text-align: justify;">
<br />
<script src="//pastebin.com/embed_js/Xf97FAqU"></script>
<br />
Y con esto completamos definitivamente el archivo auxiliar sgb.z80 (<a href="https://drive.google.com/file/d/0B5EtmvQp4iqoWkd6cDJBV3ZEcTQ/view?usp=drive_link&resourcekey=0-lACV4pjbS4NFltET6uFIgQ">DESCARGAR EL ARCHIVO</a>).<br />
<br />
Como requisito previo a la programación de la lógica debemos escribir en la dirección 0x0146 de nuestra ROM un 0x03, para indicar que soportamos la funcionalidad de Super Game Boy (<i>Game Boy Programming Manual > pág 178</i>). Ya tenemos parametrizada esta dirección en gbhw.inc, así que modificamos el segundo parámetro de la cabecera en main.asm.<br />
<br />
<script src="//pastebin.com/embed_js/uHXEp9R9"></script></div>
<br />
<h2>
Implementación de la comunicación</h2>
<div style="text-align: justify;">
Vamos a explicar con un ejemplo práctico cómo hemos definido las macros de los paquetes en sgb.z80. Cojamos nuestra macro de de MLT_REQ y comparémosla con la especificación de memoria del comando (<i>SGB Functions > SGB Command 11h - MLT_REQ</i>).</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1jz4e32mkBESYteZaq4Ps_VzoEDrlTl2DBuOcvxE4RYB5Hu2y9CtXAQ3NsjUVmNpRqlJ1vPuWNUhI44LwWrB-HLWK2RVCggWBIuzychrncLPX43Een8_6dUMQ_8JIRmBaj7qBQWRrvkw/s1600/mlt_reqspec.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1jz4e32mkBESYteZaq4Ps_VzoEDrlTl2DBuOcvxE4RYB5Hu2y9CtXAQ3NsjUVmNpRqlJ1vPuWNUhI44LwWrB-HLWK2RVCggWBIuzychrncLPX43Een8_6dUMQ_8JIRmBaj7qBQWRrvkw/s1600/mlt_reqspec.png" width="512" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">Como vemos el Super Game Boy permite un modo multijugador de hasta 4 jugadores con el Super 5 multi-player adapter de SNES</span></div>
<div style="text-align: center;">
<br /></div>
<script src="//pastebin.com/embed_js/vjga5uHK"></script>
<br />
<div style="text-align: justify;">
Vemos como el byte 1 define el número de jugadores solicitados en el modo multijugador del Super Game Boy. Nosotros parametrizamos dicho byte en nuestra macro y
especificamos con dos etiquetas las dos variantes que vamos a usar en
nuestro programa.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Todos los comandos están conformados por 16 bytes (128 bits), que es el tamaño del paquete de datos que podemos enviar. Por lo que sólo enviamos un paquete por comando. El número de paquetes por transferencia en cualquier caso puede especificarse a través de los últimos tres bits del byte 0 del primer paquete (como vemos en la especificación, byte 0: Command*8, que pasa a ocupar los 5 bits de mayor prioridad, + Length, que ocupa los 3 bits restantes), por lo que podemos enviar de 1 a 7 paquetes por transferencia. Nosotros representaremos la posibilidad de enviar más de un paquete por comando en el código del programa, aunque no se llegue a hacer uso de dicha funcionalidad.<br />
<br />
Ahora describiremos el proceso de envío de cada paquete tal y como se explica en la <i>pág 128</i> del <i>Game Boy Programming Manual</i>. Envío que realizaremos a través de los bits 4 y 5 del registro P1 (0xFF00) de la Game Boy, estos bit se corresponden respectivamente con los puertos de salida P14 y P15:<br />
<ol>
<li>empezamos la comunicación poniendo a 0 P14 y P15;</li>
<li>enviamos los 128 bits del paquete poniendo a 0 a P14 y a 1 a P15 si quieremos enviar un 0 y a 1 a P14 y a 0 a P15 si queremos enviar un 1;</li>
<li>enviamos un 0 en el bit 129 para cerrar la comunicación (P14 a 0 y P15 a 1).</li>
</ol>
Hay que tener en cuenta la siguiente lista de reglas:<br />
<ol>
<li>los valores que escribimos en P14 y P15 deben mantenerse por 5<span class="st">µs, y entre escrituras debemos poner P14 y P15 a 1 durante al menos 15</span><span class="st">µs. Teniendo en cuenta que un ciclo de reloj de Game Boy ya dura más de 23</span><span class="st">µs, ignoramos los tiempos, pero anotamos que debemos escribir un 1 en ambos puertos por cada bit enviado;</span></li>
<li><span class="st">entre el envío de un paquete y el siguiente debemos esperar un mínimo de 60 msec (unos 4 frames de Game Boy). La rutina "sgbpackettransfer_wait" se encargará de cumplir con esta espera.</span></li>
</ol>
Con todo esto presente, esta es nuestra rutina de envío de paquetes, que añadimos a main.asm.<br />
<br />
<script src="//pastebin.com/embed_js/aBcm8R60"></script>
<br />
La primera funcionalidad que va a servirse de esta rutina de envío es la de reconocer si nos encontramos o no en un Super Game Boy. Lo haremos de la siguiente manera (que viene a ser la forma recomendada en <i>SGB Functions > Detecting SGB hardware</i>):<br />
<ol>
<li>leeremos el identificador del registro P1, que además de servir para enviar información a través de los puertos es el registro que nos devuelve la información de los controles de la Game Boy. Por defecto, su lectura nos devuelve el identificador de los controles;</li>
<li>seleccionamos el modo modo dos jugadores de Super Game Boy enviando el paquete de MLT_REQ con dos jugadores como parámetro;</li>
<li>volvemos a leer el identificador del registro P1. Si es el mismo, significa que no se ha seleccionado el modo de dos jugadores y que por lo tanto no estamos en un SGB.</li>
</ol>
Ubicamos pues el siguiente código en main.asm.<br />
<br />
<script src="//pastebin.com/embed_js/SEd6MDje"></script>
<br />
La siguiente rutina se llamará "init_sgb_default", y no hace otra cosa que enviar los paquetes de inicialización recomendados por la doumentación (<i>Game Boy Programming Manual > pág 178</i>). La añadimos también a main.asm.<br />
<br />
<script src="//pastebin.com/embed_js/fHYDSQW6"></script><br />
Los comandos de transferencia CHR_TRN, PCT_TRN, y PAL_TRN usan la transferencia de VRAM para copiar sus datos a la RAM de la SNES. Estos son los pasos que debemos seguir para realizar este tipo de transferencia (tal y como se explica en <i>SGB Functions > SGB VRAM Transfers</i>):<br />
<ol>
<li>si no queremos que los datos a enviar se visualicen en la pantalla de la Game Boy debemos haber configurado previamente una máscara para el LCD de la Game Boy haciendo uso del comando MASK_EN;</li>
<li>deshabilitamos interrupciones y apagamos el LCD, para evitar que los gráficos que queremos enviar se corrompan;</li>
<li>asignamos los valores por defecto a la paleta de los gráficos del fondo de la Game Boy, que se traduce a escribir el valor 0xE4 en el registro de la paleta que se encuentra en 0xFF47 (0 blanco, 1 gris claro, 2 gris oscuro, 3 negro);</li>
<li>copiamos los 4KB de datos que queremos enviar al fondo visible del LCD de la Game Boy, la dirección a la que se deben copiar comienza en 0x9800;</li>
<li>enviamos el comando de transferencia, ya sea CHR_TRN, PCT_TRN o PAL_TRN. Los datos desplegados en el fondo visible de la Game Boy se enviarán a la SNES.</li>
</ol>
Antes de mostrar el código de la rutina, un pequeño paréntesis sobre MASK_EN. Habitualmente se usa al comienzo del programa para ocultar la visualización real del LCD de la Game Boy durante la transferencia de datos.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNLT0cBtDT_zYHSbOx_PbxsNEZEltJx9ihNcGo0JRsX8lrtcMkmqV7_E3s4OylvZYDue9zDBbosCspWg_WqemxtlT0xFR2xyOtnY9vVSxG-MD1yCYM7jks8b0vWOJt4QHA06uz2kqofgA/s1600/mask_enspec.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNLT0cBtDT_zYHSbOx_PbxsNEZEltJx9ihNcGo0JRsX8lrtcMkmqV7_E3s4OylvZYDue9zDBbosCspWg_WqemxtlT0xFR2xyOtnY9vVSxG-MD1yCYM7jks8b0vWOJt4QHA06uz2kqofgA/s1600/mask_enspec.png" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">(<i>SGB Functions > SGB Command 17h - MASK_EN</i>) </span></div>
<br />
Existen 4 posibles valores para el byte 1 del comando, nosotros usamos el valor 1 para congelar la imagen de la pantalla y el 0 para descongelarla cuando termina el proceso. Como vemos en las etiquetas que tenemos definidas en sgb.z80.<br />
<br />
<script src="//pastebin.com/embed_js/KcrnCtUV"></script><br />
Y cerrado el paréntesis, está es la rutina de transferencia de datos. La ubicaremos en main.asm.</div>
<br />
<script src="//pastebin.com/embed_js/1F82dPiP"></script>
<br />
<div style="text-align: justify;">
Como se puede ver, tenemos una rutina adicional que se llama "parsesgbbordertiles". Esta rutina nos permite ahorrar memoria en el caso de que los datos que queramos copiar sean tiles 2bpp, ya que se dedica a rellenar con ceros los bit planes 3 y 4 (que no usamos). En nuestro caso, al tratarse de tiles 4bpp, no hacemos uso de ella.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Y por último, sirviéndonos de las rutinas que hemos elaborado hasta el momento, esta sería la descripción de la rutina principal de inicialización del Super Game Boy:</div>
<ol style="text-align: justify;">
<li>comprobamos si nos encontramos en un Super Game Boy, si no lo estamos, volvemos y la rutina termina;</li>
<li>congelamos la visualización del LCD de la Game Boy durante todo el proceso;</li>
<li>enviamos los paquetes de inicialización recomendados por la documentación;</li>
<li>copiamos los 256 tiles que usaremos en el marco en la VRAM de la SNES. En dos tandas de 128;</li>
<li>copiamos la información del marco en la VRAM de la SNES;</li>
<li>copiamos la información de las paletas a usar en el propio juego en la RAM de la SNES;</li>
<li>asignamos la paleta previamente copiada como paleta a usar en el juego;</li>
<li>despejamos la VRAM de la Game Boy y descongelamos la visualización del LCD de la Game Boy para finalizar el proceso.</li>
</ol>
<div style="text-align: justify;">
Añadimos este código al fichero principal del programa main.asm (<a href="https://drive.google.com/file/d/0B5EtmvQp4iqocUlfcFBfMkpmNUk/view?usp=drive_link&resourcekey=0-oHVk3hwfHuth0BqT_2z1eA">DESCARGAR EL ARCHIVO</a>).</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<script src="//pastebin.com/embed_js/FCariRNY"></script></div>
<div style="text-align: justify;">
<br />
Si ahora ejecutamos el archivo assemble.bat del proyecto tendremos como resultado la ROM con el marco y las paletas personalizadas.<br />
<br />
<div style="text-align: center;">
<a href="https://drive.google.com/file/d/0B5EtmvQp4iqoUFN4eWI1RURmLW8/view?usp=drive_link&resourcekey=0-dy8rjkkRHjRBXwgUCuNliw"><span style="font-size: large;">DESCARGAR EL PROYECTO COMPLETO</span></a></div>
<br />
<br />
Doy por terminada la explicación de este sencillo prototipo. Naturalmente, quedan por aplicar muchas funcionalidades del Super Game Boy. Pero espero que este artículo sirva como punto de partida a la gente que se ha animado a desarrollar para Game Boy pero que no ha encontrado ningún recurso mínimamente guiado sobre el desarrollo para Super Game Boy.<br />
<br />
Todo apunte o crítica de cualquier tipo será bienvenida, y cualquier parte de la entrada es susceptible de ser modificada en caso de ser necesario.<br />
<br />
Así que sólo me queda daros ánimos. Ahora os toca implementar ese marco de Super Game Boy que siempre habéis querido diseñar. </div>
<br /></div>
</div>
</div>
</div>
</div>
</div>
</div>
Imanoleahttp://www.blogger.com/profile/03989722316939496203noreply@blogger.com0tag:blogger.com,1999:blog-2099766654099311467.post-5949355027301101432016-09-28T22:26:00.000+02:002016-12-01T22:45:00.141+01:00Games aside #0: Ensamblador en Game Boy, ¿es necesario?<div style="text-align: justify;">
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRhiL5d7p5qKQx1W7LYnz9cau6_o3Urkz7ijV-7YT2_wG2_gKjn99Jv9UTmDONkiyVWeI9iz8LU29BU2G_FtpAuzqeTivokb9Ay-mHR94gkWeHkqyzgubP8-1eUh_7A7eZmDUpXuXkETA/s1600/lenguage_comparison.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGU8pm4wGWU8DDgzsQgSWyhReBfbiopT7wdrbigH_zmndVKbol3CklMxFm1mejShiQPrJvOEKqpfG_3BGHtHJC1Z6cZpxrYDn4q8jaYYPCzwoLxyKXdp_GSoqNZ15j7gq7gP1ifuF8978/s400/lenguage_comparison.png" width="400" /> </a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-size: x-small;">Izquierda: prototipo presentado <a href="https://imanoleasgames.blogspot.com.es/2016/09/last-crown-warriors-0-accion-tactica-en.html">aquí</a>; derecha: nuevo prototipo en ensamblador.</span> </div>
<br />
Recientemente he terminado de portar todo el código del <a href="https://imanoleasgames.blogspot.com/2016/09/last-crown-warriors-0-accion-tactica-en.html">prototipo</a> de <a href="https://imanoleasgames.blogspot.com/search/label/Last%20Crown%20Warriors">Last Crown Warriors</a> mostrado en este blog a ensamblador. Sentía que el programa original, realizado con una combinación de C y ASM, no garantizaba un rendimiento óptimo, y que no sería la mejor base sobre la que fundamentar el resto del programa: tarde o temprano iba a terminar recurriendo a las virtudes de la programación de bajo nivel, y las herramientas que estaba usando, a pesar de ofrecer la posibilidad de añadir rutinas en ensamblador al programa, no presentaban las mismas ventajas que ofrece un programa realizado íntegramente en lenguaje ensamblador.<br />
<br />
Por eso, aprovechando la ocasión de tener dos programas de resultado casi idéntico (uno en ASM, otro en C+ASM) para Game Boy, me he decidido a realizar una sencilla comparativa de rendimiento en ambos.<br />
<br />
No es mi objetivo hacer un análisis en profundidad y concienzudo, ni mucho menos, pero sí sacar a la luz cuál es el resultado real que se obtiene cuando se desarrolla haciendo uso de las principales herramientas de las que la escena de Game Boy actualmente dispone.<br />
<br />
<span style="font-size: large;">C+ASM versus ASM </span><br />
<br />
Antes de comenzar, creo conveniente aclarar por qué en este caso no se encuentra representada la opción de sólo C. Sencillamente, la desestimé. El deseo de tener un gran número de enemigos en pantalla con un rendimiento óptimo se contradecía con mi experiencia previa en desarrollos basados únicamente en C y orientados al sistema de marras.<br />
<br />
Para empezar, toca concretar qué herramientas se han usado para la elaboración de la ROM en cada uno de los casos: Para el programa de C y ensamblador usé <a href="http://gbdk.sourceforge.net/">GBDK (Game Boy Development Kit)</a>, una versión modificada del <a href="http://sdcc.sourceforge.net/">SDCC (Small Device C Compiler)</a> orientada a la Game Boy con librerías dedicadas y ejemplos. Decir que lleva sin actualizarse desde mediados de 2002.<br />
<br />
En este programa el código en C, si bien no busca la optimización más absoluta, si se encuentra realizado siguiendo las <a href="http://gbdk.sourceforge.net/guidelines.html">directrices recomendadas</a> por la herramienta. Se delegan además la operaciones matemáticas complejas y las funciones grandes recurrentes o relativamente simples a rutinas en ASM. Concretamente en este lenguaje de bajo nivel se cumplen los siguientes procesos:<br />
<ul>
<li>actualización y posprocesado de sprites; </li>
<li>inteligencia artificial de los enemigos;</li>
<li>detección de entorno y procesado de hierba;</li>
<li>multiplicaciones y divisiones con resto;</li>
<li>generación de números aleatorios;</li>
<li>actualización gráfica durante el <a href="https://en.wikipedia.org/wiki/Vertical_blanking_interval">VBLANK</a>.</li>
</ul>
Por lo tanto queda en manos de C el control del héroe, su sistema de colisión avanzada, la actualización de la interfaz de usuario, la animación del fondo, y el control general del programa.<br />
<br />
Cabe destacar que el rendimiento de las rutinas mencionadas en el programa basado en C es menor que el de sus homónimas en el programa completamente en ensamblador. La razón es simple, en bajo nivel cuando queremos acceder a un dato lo hacemos directamente a través de su dirección, en C la memoria se maneja de manera dinámica y por lo tanto no es viable acceder a un dato de esta forma. A menos, claro está, que también decidamos controlar las direcciones de cada una de las variables, perdiendo así una de las ventajas que C nos ofrece. En el caso del prototipo se pasan todos los parámetros en forma de variables a través de una <a href="https://es.wikipedia.org/wiki/Pila_(inform%C3%A1tica)">pila</a>, apilando todos los datos de referencia que necesitamos primero para luego desapilarlos en la rutina de ASM antes de gestionarlos. Este proceso adicional perjudica ligeramente a la rapidez de dichas rutinas.<br />
<br />
Resultado, hasta cinco enemigos moviéndose simultáneamente en pantalla sin ralentizaciones de ningún tipo. La barra verde a la derecha de la imágen indica la carga del procesador, si el verde claro sobrepasase el alto de la barra significaría que existe una carga de trabajo por frame mayor a la que el procesador puede hacer frente y surgirían ralentizaciones.<br />
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen="" class="giphy-embed" frameborder="0" height="290" src="//giphy.com/embed/26hirMERbslnl0I2A" width="480"></iframe><br /></div>
<div style="text-align: center;">
<span style="font-size: x-small;">Programa en C+ASM.</span></div>
<a href="https://giphy.com/gifs/game-boy-development-homebrew-3o7TKRJarrlDSUUSVq"></a><br />
Y aquí tenemos ese mismo resultado con el programa elaborado enteramente en ASM con <a href="https://github.com/bentley/rgbds">RGBDS (Rednex Game Boy Development System)</a>, un ensamblador que hoy día sigue recibiendo actualizaciones. En este programa se ha realizado una transición de la lógica original a este lenguaje, priorizando en todo momento la optimización de recursos y procesamiento.<br />
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen="" class="giphy-embed" frameborder="0" height="290" src="//giphy.com/embed/l0MYM229WAV40G7XG" width="480"></iframe>
</div>
<div style="text-align: center;">
<span style="font-size: x-small;"> Programa en ASM puro.</span></div>
<div style="text-align: center;">
<br /></div>
Como se puede observar la carga del procesador es notablemente menor. Y aquí tenemos el programa de nuevo esta vez con nueve enemigos en movimiento, algo inviable en el prototipo anterior, llegando así a cubrir el número máximo de sprites en pantalla a nivel de hardware (si contamos los sprites de hierba asociados a cada personaje).<br />
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen="" class="giphy-embed" frameborder="0" height="290" src="//giphy.com/embed/3o7TKOUAQRuDIO2c24" width="480"></iframe>
</div>
<div style="text-align: center;">
<span style="font-size: x-small;"> Programa en ASM puro, con número de enemigos máximizado.</span></div>
</div>
<br />
<div style="text-align: left;">
Así que, ensamblador en Game Boy, ¿es necesario? Creo que depende del proyecto que se quiera desarrollar. Para <a href="https://imanoleasgames.blogspot.com.es/search/label/Last%20Crown%20Warriors">Last Crown Warriors</a>, un juego que pretende mostrar de manera simultánea el mayor número posible de personajes distintos en movimiento, definitivamente sí.</div>
<br />Imanoleahttp://www.blogger.com/profile/03989722316939496203noreply@blogger.com8tag:blogger.com,1999:blog-2099766654099311467.post-12292295297333197332016-09-05T00:58:00.000+02:002016-12-01T22:48:48.918+01:00Last Crown Warriors #0: Acción táctica en Game Boy<div style="text-align: justify;">
<span class="" id="result_box" lang="en">Last Crown Warriors en un nuevo proyecto paralelo para Game Boy. Su nombre proviene del <a href="https://imanoleasgames.blogspot.com.es/2015/07/last-crown-bitbit-jam-2015.html">juego</a> que presenté en la <a href="http://bitbitjam.com/BBJ015">BitBit Jam 2015</a>.</span></div>
<div style="text-align: justify;">
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBx7gpXzOwKfvVDTw_4I7qlItb7tLf-lIXvKzhT59oSjp0c5gT2kzzXc7vuOmqcE0S2WND8vQmiofQY1KnmNgezmAwrbP9bQo-TYU5rQPMrj3ihGu6x5S-VrISPFiO1XgOUzAKj7ECyjc/s1600/comparison.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="216" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBx7gpXzOwKfvVDTw_4I7qlItb7tLf-lIXvKzhT59oSjp0c5gT2kzzXc7vuOmqcE0S2WND8vQmiofQY1KnmNgezmAwrbP9bQo-TYU5rQPMrj3ihGu6x5S-VrISPFiO1XgOUzAKj7ECyjc/s640/comparison.png" width="480" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Izquierda: Last Crown (BitBit Jam 2015); Derecha: Last Crown Warriors (en desarrollo)</td></tr>
</tbody></table>
<div style="text-align: justify;">
<span class="" id="result_box" lang="en"><br /></span>
<span class="" id="result_box" lang="en">El juego en cuestión ha sido replanteado y reprogramado con una mezcla de C y ensamblador, dando prioridad a conseguir procesar un gran número de enemigos.</span></div>
<div style="text-align: justify;">
<span class="" id="result_box" lang="en"><br /></span>
<span class="" id="result_box" lang="en">La idea inicial de este nuevo proyecto se resume en conseguir aunar las mecánicas de control de los <a href="https://es.wikipedia.org/wiki/The_Legend_of_Zelda:_Link%27s_Awakening">Zelda</a> de Game Boy con la acción táctica característica de la serie de videojuegos <a href="https://en.wikipedia.org/wiki/List_of_Warriors_video_games">Warriors</a> (o Musou).</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="clear: left; float: right; margin-bottom: 1em; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihuA7TVvW9EWdgkQzoOzzuk9A7CCkAL6OugYfNXvDcLAyYkrYtaTE92eprjGNcgulKqHQVY7kBjjC15GHPqGYZeDNSGlQk4moDJMqmEgBxMlD2OpCg6gXxDJRFWe1vswOL89EHZ777L5A/s1600/Dynasty_Warriors_2_Case.jpg" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihuA7TVvW9EWdgkQzoOzzuk9A7CCkAL6OugYfNXvDcLAyYkrYtaTE92eprjGNcgulKqHQVY7kBjjC15GHPqGYZeDNSGlQk4moDJMqmEgBxMlD2OpCg6gXxDJRFWe1vswOL89EHZ777L5A/s200/Dynasty_Warriors_2_Case.jpg" width="140" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Dynasty Warriors 2 (2000), PS2 </td></tr>
</tbody></table>
<span class="" id="result_box" lang="en"><table cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdhJ3GdDnABDX4jsoNJh6wZZq3yb5rgrpMxkN-lHJzElZEmP4SGBVgtQ7umN53YsTH4XXlnseo2PCnfVt4yrf0TnXZlIjxr6QaDqhN55Z6TTiEvwRHFGA6kHJ1HuTDr4zRRr6tLWTVGuA/s1600/Caratula_LA.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdhJ3GdDnABDX4jsoNJh6wZZq3yb5rgrpMxkN-lHJzElZEmP4SGBVgtQ7umN53YsTH4XXlnseo2PCnfVt4yrf0TnXZlIjxr6QaDqhN55Z6TTiEvwRHFGA6kHJ1HuTDr4zRRr6tLWTVGuA/s200/Caratula_LA.jpg" width="199" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The Legend of Zelda Link's Awakening (1993), Game Boy</td></tr>
</tbody></table>
</span><span class="" id="result_box" lang="en"><span class="" id="result_box" lang="en"></span></span><span class="" id="result_box" lang="en"><span class="" id="result_box" lang="en"> </span></span><br />
<span class="" id="result_box" lang="en"><span class="" id="result_box" lang="en">Existen algunos títulos que también han intentado juntar acción clásica con estrategia, como el reciente <a href="http://www.nintendo.com/games/detail/gotta-protectors-3ds">Gotta Protectors</a> de la saga <a href="https://en.wikipedia.org/wiki/Protect_Me_Knight">Protect Me Knight</a>.</span></span></div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2aFx9B6rMymVnqcVuDraxHEXeLY8AXyAESsJuSavyIPsPUEfhldpyimAZtvweIoUvSFlUk6D6x0jvcloDqrsh6ZHONKAvwSpwy57KolQHY_rMg86qilz1VlzgsrV8FS4qm-PwMst_VtA/s1600/gottaprotectors.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2aFx9B6rMymVnqcVuDraxHEXeLY8AXyAESsJuSavyIPsPUEfhldpyimAZtvweIoUvSFlUk6D6x0jvcloDqrsh6ZHONKAvwSpwy57KolQHY_rMg86qilz1VlzgsrV8FS4qm-PwMst_VtA/s400/gottaprotectors.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Gotta Protectors (2016), 3DS</td></tr>
</tbody></table>
<div style="text-align: justify;">
<span class="" id="result_box" lang="en"><span class="" id="result_box" lang="en">El equipo del proyecto será el mismo que el de <a href="https://imanoleasgames.blogspot.com.es/search/label/Rocket%20Man">Rocket Man</a>, con <a href="https://twitter.com/seiyouh">Seiyouh</a> a cargo de la elaboración de gráficos, <a href="https://twitter.com/NAP_VGM">NAP.VGM</a> haciendo músicas y efectos de sonido y yo (<a href="https://twitter.com/Imanolea">Imanolea</a>) como responsable del diseño y la programación.</span></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span class="short_text" id="result_box" lang="en"><span class="">En este vídeo puede verse una primera demostración técnica del programa, con cinco enemigos simultáneos en pantalla.</span></span><br />
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen="" frameborder="0" height="283" src="https://www.youtube.com/embed/3jVeCetqGk0" width="504"></iframe>
</div>
<div style="text-align: center;">
<br /></div>
</div>
Imanoleahttp://www.blogger.com/profile/03989722316939496203noreply@blogger.com0tag:blogger.com,1999:blog-2099766654099311467.post-40401800641711738912016-07-04T16:36:00.004+02:002023-11-22T11:46:11.153+01:00Akaru Hime: The Red Princess (BitBitJam3)Game Boy game made during a week for <a class="hashtag" href="http://gamejolt.com/tag/BitBitJam3" title="#BitBitJam3">#BitBitJam3</a><br />
<br />
The Prophecy says that every thousand years Koga Ninja try to steal Hino's family jewel. The time has come. Akaru-hime, also known as The Red Princess, is willing to protect her family's treasure, even with her own blood...<br />
<div style="text-align: center;">
<br /></div><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" class="BLOG_video_class" height="266" src="https://www.youtube.com/embed/AvOfC_sOKYc" width="320" youtube-src-id="AvOfC_sOKYc"></iframe> <b> </b></div>
<div style="text-align: center;">
<br /></div>
<b>Team:</b> Imanol Barriuso (<a href="https://twitter.com/Imanolea">Imanolea</a>), Belinda Barriuso (<a href="https://twitter.com/Leia83">Leia83</a>), Sergio Presa (<a href="https://twitter.com/LocoMJJ">LocoMJJ</a>). <br />
<b>System:</b> Game Boy<br />
<h2 style="text-align: center;">
<a href="http://gamejolt.com/games/akaru-hime-the-red-princess/162393">GAME PAGE</a></h2>
Imanoleahttp://www.blogger.com/profile/03989722316939496203noreply@blogger.com1tag:blogger.com,1999:blog-2099766654099311467.post-87683371710843174672016-06-26T15:10:00.001+02:002022-09-12T18:08:17.630+02:00Rocket Man (Demo)Action platformer game made for the Nintendo Game Boy.<br />
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen="" frameborder="0" height="283" src="https://www.youtube.com/embed/jAUgdxCghyM" width="504"></iframe>
</div>
<br />
<b>System:</b> Nintendo Game Boy<br />
<br />
<b>Programming and design:</b> <a href="https://twitter.com/Imanolea">Imanolea</a><br />
<b>Graphics:</b> <a href="https://twitter.com/seiyouh">Seiyouh</a><br />
<b>Music and sound effects:</b> <a href="https://twitter.com/NAP_VGM">NAP.VGM</a><br />
<br />
<b>Releaste notes</b><br />
<b>v1.1 (december 28, 2016)</b><br />
- Super Game Boy support added: custom frame and custom game palettes.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7p_6Nb4DnDcyQvFtjPzQYMGNExMKoAPaExgQ0L7-U_mVt2u_YI4tpyPz6m5ZI3JA33EqMntzj9-l4DYhMBCehuU8FpZgukKX-9qthdCMEoO1fdZctFEn__Mx6RxEQlspP6cXD07J8qW4/s1600/rocketmansgb.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="280" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7p_6Nb4DnDcyQvFtjPzQYMGNExMKoAPaExgQ0L7-U_mVt2u_YI4tpyPz6m5ZI3JA33EqMntzj9-l4DYhMBCehuU8FpZgukKX-9qthdCMEoO1fdZctFEn__Mx6RxEQlspP6cXD07J8qW4/s320/rocketmansgb.png" width="320" /></a></div>
<b>v1.2 (may 19, 2017)</b><br />
- Added face animation and scroll to chats<br />
- Light redesign<br />
- Screen falling bug fixed<br />
- Noise channel sound effect bug fixed<br />
<br />
<b>v1.2.1 (july 21, 2017)</b><br />
<b>- </b>Added Light Games references to the title and credits screen.<br />
<br />
<div style="text-align: center;">
<span style="font-size: x-large;"><a href="https://drive.google.com/file/d/0B5EtmvQp4iqodk1BcHFQZ2pBVUE/view?resourcekey=0-n9Vg_ipI9m0K1ZxsP0k5zg">ROM DOWNLOAD (DEMO)</a></span> </div>
Imanoleahttp://www.blogger.com/profile/03989722316939496203noreply@blogger.com6tag:blogger.com,1999:blog-2099766654099311467.post-20897985495436392132015-11-07T11:45:00.000+01:002015-11-07T11:45:21.430+01:00Rocket Man #14: ¡Corre Rocket Man, corre!Se han realizado mejoras en el motor del juego. Una de ellas consiste en el <b>soporte </b>de<b> enemigos de cualquier tamaño</b> con el objetivo de hacer aparecer enemigos grandes, como puede ser un <b>jefe</b> de <b>final</b> de fase.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgM6HnSK6BfyibfYAhUVvbVTGUaJVVZxN67AFKwArEFPsIbciRF8qPGyE5bUcSX2RSAeWijg4btdUsXU48goVleur5xrv2DorBcfWd7UxIJj8rBVrbnhV4GjV7UgSPxpn9y3ioec-z4sZc/s1600/jefeDeFinalDeFase.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="242" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgM6HnSK6BfyibfYAhUVvbVTGUaJVVZxN67AFKwArEFPsIbciRF8qPGyE5bUcSX2RSAeWijg4btdUsXU48goVleur5xrv2DorBcfWd7UxIJj8rBVrbnhV4GjV7UgSPxpn9y3ioec-z4sZc/s320/jefeDeFinalDeFase.png" width="320" /></a></div>
<br />
En la parte gráfica se han producido avances en el diseño de artes oficiales, teniendo acabados los primeros <b>artes de cuerpo completo</b> de <b>Rocket Man</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjB96nvlGnPPPAHaRfeY963sE7QEbUVCyWxI4-SDl5VCDNM3blg683MiqbvXFEj_Mn6pKMRKog1VdblpkW_gjUz6w9OVSWwmLxC9M7QzDiUp12ItJQFx5m94f_-V4b-ZiReA_4plKR9wds/s1600/Cuerpo-RocketMan-DeFrente-Color.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjB96nvlGnPPPAHaRfeY963sE7QEbUVCyWxI4-SDl5VCDNM3blg683MiqbvXFEj_Mn6pKMRKog1VdblpkW_gjUz6w9OVSWwmLxC9M7QzDiUp12ItJQFx5m94f_-V4b-ZiReA_4plKR9wds/s320/Cuerpo-RocketMan-DeFrente-Color.png" width="113" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhomozbySXwpyQjWbwxlkIW4djf7FRxLqnm82WLpBvEfeOMvMxk-oIhurC62u51uEe18LCUoGH5m5vnC4WBISYcnoGvN1VdhVYRr1jYuY4FD46nYyvnZ_DUrq2yubWqVmkucS7WvL1WBvQ/s1600/RocketMan-CuerpoPerfil-Color.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhomozbySXwpyQjWbwxlkIW4djf7FRxLqnm82WLpBvEfeOMvMxk-oIhurC62u51uEe18LCUoGH5m5vnC4WBISYcnoGvN1VdhVYRr1jYuY4FD46nYyvnZ_DUrq2yubWqVmkucS7WvL1WBvQ/s320/RocketMan-CuerpoPerfil-Color.png" width="110" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Y, por primera vez, estos artes reciben sus primeras <b>adaptaciones</b> con <b>gráficos del propio juego</b>. En este caso representando el <b>icono del personaje</b> y el de las <b>vidas</b>.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhh3M6Turg8MBKnYCXTbaORwEXRV9RJwOJlDBSrxg7lD3K4gNY0paJnatnCZ8chqfIaiSPJVo-cETOmJ-vYNhT68HjGjeXqfYXq_FkTcei3GN0tZEJk-nRmsOMX2CE6XehpFM3oWt1Q4ZM/s1600/arteIcono.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="88" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhh3M6Turg8MBKnYCXTbaORwEXRV9RJwOJlDBSrxg7lD3K4gNY0paJnatnCZ8chqfIaiSPJVo-cETOmJ-vYNhT68HjGjeXqfYXq_FkTcei3GN0tZEJk-nRmsOMX2CE6XehpFM3oWt1Q4ZM/s320/arteIcono.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnxpb-n0H0DKbNsOWGP1NcinKelhhi3c2nHWT6be-pzttwwy3qhNpaKtSo6wkNo0Eit7Kk2KXRXt7BxAMi78xvwvTunTDw9-tx30w3iNxHW-2e-L-XpXdebs2ccrPFMy-AfHqRRI04F_k/s1600/arteVidas.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnxpb-n0H0DKbNsOWGP1NcinKelhhi3c2nHWT6be-pzttwwy3qhNpaKtSo6wkNo0Eit7Kk2KXRXt7BxAMi78xvwvTunTDw9-tx30w3iNxHW-2e-L-XpXdebs2ccrPFMy-AfHqRRI04F_k/s1600/arteVidas.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
También se ha trabajado en permitir el recorrido bidireccional de <b>mapas grandes</b>, capaces de contener en su interior <b>fases completas</b>. El vídeo de la entrada muestra la longitud alcanzada con un mapeado de prueba.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen="" frameborder="0" height="283" src="https://www.youtube.com/embed/rE4FZ26K0Rc" width="504"></iframe></div>
<div style="text-align: center;">
<br /></div>
Imanoleahttp://www.blogger.com/profile/03989722316939496203noreply@blogger.com4tag:blogger.com,1999:blog-2099766654099311467.post-30293398654408036972015-10-05T23:46:00.002+02:002015-10-05T23:59:44.116+02:00Rocket Man #13: Sonido I (Música)Rocket Man ya cuenta con <b>música propia</b>. Su <b>autor</b> es <b>NAP.VGM</b>, que va a ser el encargado de la parte sonora del juego, aportando tanto música como efectos de sonido.<br />
<br />
Para componer estas pistas se ha usado el <i>tracker </i><a href="http://www.delek.com.ar/deflemask"><b>Deflemask</b></a> y para la incorporación de las composiciones generadas por el mismo en el juego se ha realizado una <b>ingeniería inversa</b> de la <i>rom</i> de Game Boy que genera la herramienta con el objetivo de extraer y adaptar tanto los datos del sonido como las rutinas de reproducción.<br />
<br />
Una implementación inicial de estas rutinas adaptadas permite <b>la reproducción de pistas en el juego</b>, aunque <b>se sigue trabajando</b> por la parte de programación para lograr la <b>reproducción simultánea</b> de música y efectos de sonido.<br />
<br />
<div style="text-align: center;">
<iframe allowfullscreen="" frameborder="0" height="283" src="https://www.youtube.com/embed/Cemowwf-0hI" width="504"></iframe>
</div>
<div style="text-align: center;">
<br /></div>
Además de esto se está invirtiendo tiemo en <b>ampliar las capacidades</b> del motor del juego de cara a abordar un primer nivel completo.<br />
<br />
Y respecto al apartado visual se planea el diseño de <b>gráficos más elaborados</b> en base a una serie de artes oficiales. Estos gráficos tendrían como objetivo la <b>presentación de personajes y sucesos</b> de la historia. Una serie de nuevos artes representan el aspecto de Rocket Man, concretamente el rostro.<br />
<div style="text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiguH10ITNLJVVKm-epE9bLqzNTPIqNBztdwPh755AHWS6t1QtpErwdJokR88NkG_5sFTG9hwr8pcTATPnE0qj9GRKOb6TXYGDZp-7SamxyT4GFokjNxc0ilxNvbqeTyqQV7yp6c_VnT0/s1600/Rostro-RocketMan-DeLado-Color.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiw9hucgSy5tx6jIaBE8NucS6tIsFDDeUCEthxZXQxk32B_tqtqiBuPwoo7bs66LPzf2NC7So9ApxVcaiRZLu8Fy3DZEslhk0vcRnJ9P7SbJTfoCTYve50pzRhM-i2Rm0FPC5zfhCDrHcY/s1600/Rostro-RocketMan-DeFrente-Color.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiw9hucgSy5tx6jIaBE8NucS6tIsFDDeUCEthxZXQxk32B_tqtqiBuPwoo7bs66LPzf2NC7So9ApxVcaiRZLu8Fy3DZEslhk0vcRnJ9P7SbJTfoCTYve50pzRhM-i2Rm0FPC5zfhCDrHcY/s320/Rostro-RocketMan-DeFrente-Color.png" width="284" /></a></div>
<div style="text-align: center;">
<img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiguH10ITNLJVVKm-epE9bLqzNTPIqNBztdwPh755AHWS6t1QtpErwdJokR88NkG_5sFTG9hwr8pcTATPnE0qj9GRKOb6TXYGDZp-7SamxyT4GFokjNxc0ilxNvbqeTyqQV7yp6c_VnT0/s320/Rostro-RocketMan-DeLado-Color.png" width="283" />
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtWjj3iSOeZuTayLVYla6MAZLUVOB_YrijbCnG-nAM6-KV3QAyI_F1uJQkziirwkv4Pfc7J-qUK7egLQ8uIF4THK5NFOwBLlddrplK9dqk5xGEfYrlYXVihiPeq3cwqOrVo6iGuAquYdY/s1600/Rostros-RocketMan-BN.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="232" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtWjj3iSOeZuTayLVYla6MAZLUVOB_YrijbCnG-nAM6-KV3QAyI_F1uJQkziirwkv4Pfc7J-qUK7egLQ8uIF4THK5NFOwBLlddrplK9dqk5xGEfYrlYXVihiPeq3cwqOrVo6iGuAquYdY/s320/Rostros-RocketMan-BN.jpg" width="320" /></a></div>
<br />Imanoleahttp://www.blogger.com/profile/03989722316939496203noreply@blogger.com0tag:blogger.com,1999:blog-2099766654099311467.post-55998033142968079022015-07-28T00:05:00.000+02:002016-07-04T15:59:12.033+02:00Last Crown (BitBit Jam 2015)Videojuego creado en 48 horas para la BitBit Jam durante la Euskal Encounter 23.<br />
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen="" frameborder="0" height="283" src="https://www.youtube.com/embed/P3PAHnSarw8" width="504"></iframe>
</div>
<div style="text-align: center;">
<b><br /></b></div>
<div style="text-align: left;">
<b>Equipo de desarrollo:</b> Imanol Barriuso, Sergio Presa (<a href="https://twitter.com/LocoMJJ">LocoMJJ</a><a href="https://twitter.com/LocoMJJ"></a>), Belinda Barriuso (<a href="https://twitter.com/Leia83">Leia83</a>)</div>
<br />
<b>Plataforma:</b> Game Boy.<br />
<b>Fecha de finalización:</b> 26 de julio de 2015.<br />
<br />
<b>Juego:</b> <a href="http://bitbitjam.com/">BitBit Jam</a><br />
<br />Imanoleahttp://www.blogger.com/profile/03989722316939496203noreply@blogger.com2tag:blogger.com,1999:blog-2099766654099311467.post-5300200477398987182015-07-07T20:25:00.001+02:002015-07-08T07:32:34.779+02:00Rocket Man #12: AvancesSe ha trabajado en implementar mecánicas típicas como <b>muerte y reinicio</b> del nivel así como la consiguiente <b>reducción</b> en el <b>número de vidas</b>.<br />
<br />
También se han añadido <b>transiciones adicionales</b> en la <b>pantalla de título</b> y un <b>iluminado progresivo</b> al <b>iniciar</b> el nivel.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCyciMAaYDKnve8vhO-xiiSS7hA9rX8Av4exp3QNZzgEyk0b4UIeED4nkbWtAPHf1I8rttijgYUJobXKVx4fv5ymAWVdvqCsnNp3OvDoC4KzJF7W1JE0QoGwcS1rNmTrSvVMRaAIPnjdY/h400/insta.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" target="_blank"><img border="0" height="178" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8fhdJaZmAxiSjZffpt781RQTxpgrlya9Gr6tqj8vbmlCkbbJOhJ_tN9WrvG7bGRRLpw-vBQL7tcqYaAAmH7Uda3XeYZmbhT9WLdIvSeEOSUfBCf5xmmJ-BHktIKd1LJtHZqBLhNSzSjA/s200/iluminado.png" width="200" /></a></div>
<br />
Ahora todos los <b>proyectiles</b> se <b>desintegran</b> al <b>colisionar</b> con personajes o con partes sólidas del escenario. <b>Excepto</b> los que sean <b>explosivos</b>, los cuales estallarán.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-dZrkSGhjrpxxeGPrjzqY5X6P_pJosSxg-nAG0eP4cidp-2ezX9FS2ndlaSflCDu_SzOX-mJPNZcCJTnjw3CYsfwgTKMl3IQPHllHDtYzGGKBHAfZ0eydVB_HarSFVjs0zKXMIMn7P5c/s1600/desintegraci%25C3%25B3n.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="140" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-dZrkSGhjrpxxeGPrjzqY5X6P_pJosSxg-nAG0eP4cidp-2ezX9FS2ndlaSflCDu_SzOX-mJPNZcCJTnjw3CYsfwgTKMl3IQPHllHDtYzGGKBHAfZ0eydVB_HarSFVjs0zKXMIMn7P5c/s320/desintegraci%25C3%25B3n.png" width="320" /></a></div>
<br />
<br />
Se ha creado un <b>nuevo enemigo</b> que utiliza estos proyectiles. Cuenta además con un <b>escudo</b> con el que es capaz de <b>defenderse</b> de nuestros disparos.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEht-KybxmQXFIqnulPehtdwG1BML6vu07qEE-Wgkraa5YrXluebjO87-3JGu4aDGupjo_SddaUiNiqQPXp-SQm6AsJicIgE8-Wli28M0ReItfBAZGrL8ED8P2adailvUu3b0CCzqUUFzdU/s1600/lanzabombas.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEht-KybxmQXFIqnulPehtdwG1BML6vu07qEE-Wgkraa5YrXluebjO87-3JGu4aDGupjo_SddaUiNiqQPXp-SQm6AsJicIgE8-Wli28M0ReItfBAZGrL8ED8P2adailvUu3b0CCzqUUFzdU/s1600/lanzabombas.png" /></a></div>
<br />
<br />
Este enemigo es una variante del que realiza disparos. Un <b>nuevo arte</b> representa el aspecto de estos personajes.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinuNk58cnbXcIWMihLzH1RTtI7dj5xDzjFSFoAuiM8XMY6755wpo_dD7YDTl26wIOz0KkFvFY2BLMcmwYVRis9cV65HP33S8y6fwp5yppzRTzxcc5FUFiRajY0knx4ojXb2t6gT4SUfzo/s1600/Enemigo1-ArteColor.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinuNk58cnbXcIWMihLzH1RTtI7dj5xDzjFSFoAuiM8XMY6755wpo_dD7YDTl26wIOz0KkFvFY2BLMcmwYVRis9cV65HP33S8y6fwp5yppzRTzxcc5FUFiRajY0knx4ojXb2t6gT4SUfzo/s320/Enemigo1-ArteColor.jpg" width="212" /></a></div>
<div style="clear: both; text-align: center;">
<span style="font-size: x-small;">Robot hostil</span></div>
<div style="clear: both; text-align: center;">
<div style="text-align: left;">
<br />
<div style="text-align: center;">
<iframe allowfullscreen="" frameborder="0" height="283" src="https://www.youtube.com/embed/CAUYzTMLch0" width="504"></iframe></div>
</div>
</div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: left;">
Es importante aclarar que los cuatro iriqmksw uyi wi irgyirxver egxyepqirxi ir ip nyiks jsvqer tevxi hip inivgmxs hi Pmklx. Vmzep hi Vsgoix Qer c erxeksrmwxe hip nyiks.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMzdc1sxPqtjsrOiEAhezT-0dT4OgbbLCQu8Nf5NKnmiCoteo9m5VvcTKL_3h4AsAHWYGVHGRsgSsXVko4Mn69sS11LyDu5uJg6OGW0Jv9cuU1IWACY8ZHiPnXDht_hIts1KpMd_MOQNI/s1600/Pmklx.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMzdc1sxPqtjsrOiEAhezT-0dT4OgbbLCQu8Nf5NKnmiCoteo9m5VvcTKL_3h4AsAHWYGVHGRsgSsXVko4Mn69sS11LyDu5uJg6OGW0Jv9cuU1IWACY8ZHiPnXDht_hIts1KpMd_MOQNI/s320/Pmklx.png" width="276" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div style="text-align: center;">
<span style="font-size: x-small;">Pmklx</span></div>
<div style="text-align: center;">
<span style="background-color: white;"><span style="font-size: x-small;"><br /></span></span></div>
Imanoleahttp://www.blogger.com/profile/03989722316939496203noreply@blogger.com3tag:blogger.com,1999:blog-2099766654099311467.post-69721886058535572522015-04-06T21:02:00.002+02:002015-07-07T20:24:48.546+02:00Rocket Man #11: MejorasSe ha realizado una modificación en la mecánica de activación del cohete. <b>Rocket Man</b> necesitará que se <b>mantenga pulsado</b> el <b>botón de salto</b> en el aire para <b>volar</b>. De esta forma, será más fácil definir un tiempo de vuelo concreto para esquivar proyectiles enemigos o llegar a determinadas zonas del mapa.<br />
<br />
El juego ahora soporta hasta <b>tres enemigos simultáneos</b> en pantalla. Y con ello llega también un <b>nuevo enemigo volador</b> capaz de desplazarse por el mapa.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgK26niiREVVkHy08A6f87i4iUGLpiKRnMBKXnDirZnBoCxfrWp9eEzFZFTrHFYbcz4Wi8c_hGiIpPBrJ5VrOMkdyM-amOC-OGCJ1lWnqo3PsLACgn03rNDFeWZ49-dOGeVqTx09PyHmOs/s1600/3enemies.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="252" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgK26niiREVVkHy08A6f87i4iUGLpiKRnMBKXnDirZnBoCxfrWp9eEzFZFTrHFYbcz4Wi8c_hGiIpPBrJ5VrOMkdyM-amOC-OGCJ1lWnqo3PsLACgn03rNDFeWZ49-dOGeVqTx09PyHmOs/s1600/3enemies.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
También se ha añadido una <b>pantalla de título</b> y un <b>efecto de transición</b> al <b>iniciar el nivel</b>. Aquí un vídeo con las novedades en acción.</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen="" frameborder="0" height="283" src="https://www.youtube.com/embed/UEcG7bmLKIo" width="504"></iframe></div>
<div style="text-align: center;">
<br /></div>
Imanoleahttp://www.blogger.com/profile/03989722316939496203noreply@blogger.com2tag:blogger.com,1999:blog-2099766654099311467.post-47339107177850896522015-02-24T16:42:00.003+01:002015-02-24T16:44:56.248+01:00Rocket Man #10: Combate<b>Rocket Man</b> recibe un <b>impacto</b> cuando colisiona con los <b>proyectiles</b> enemigos. Estos impactos también afectarán a su <b>barra de salud</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjZMPFNPR1im3A1Fy3KhB1QTTwyMsEZeCKFwKAUQyo7NjckxWB75yy6joR9ssFU6D31zU8A-GXbFxOdoEUOM09ylRyS02DdA41AstnW5HqO-L1kB63C2Vc3gqsppNInL5ojqXSNogLE1E/s1600/impacto.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjZMPFNPR1im3A1Fy3KhB1QTTwyMsEZeCKFwKAUQyo7NjckxWB75yy6joR9ssFU6D31zU8A-GXbFxOdoEUOM09ylRyS02DdA41AstnW5HqO-L1kB63C2Vc3gqsppNInL5ojqXSNogLE1E/s1600/impacto.png" height="207" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtsbYLTJbqAClooFQDMMsgiGNPBpihaA7AxxJTEiHqrUr2yrA6H2U7KhYXMbyqLqQGnugaxwBeMDg9-r1H1B3Eq-H3o4SrUiEPKb07GsZanAnImmk0ycFlW9zSKfDhvdpX5VSPJxZ6xZk/s1600/barraSalud.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtsbYLTJbqAClooFQDMMsgiGNPBpihaA7AxxJTEiHqrUr2yrA6H2U7KhYXMbyqLqQGnugaxwBeMDg9-r1H1B3Eq-H3o4SrUiEPKb07GsZanAnImmk0ycFlW9zSKfDhvdpX5VSPJxZ6xZk/s1600/barraSalud.png" height="93" width="320" /></a></div>
<br />
El comportamiento del <b>segundo enemigo</b> se ha desarrollado. Ahora suelta <b>proyectiles</b> en distintas direcciones <b>al morir</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgajAUIbx97K3O08F831rcANepMt1YSYktge7IatLElkVF8pl_pXEyEl1Mq2xaknL359CvfZr7iL_u7fcg6vgaHzpL-rcktPuYGkr6gT9xczh1FHhuOP0zc3r_tZhyphenhyphenenMekVdpIkz9r-2M/s1600/explosion.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgajAUIbx97K3O08F831rcANepMt1YSYktge7IatLElkVF8pl_pXEyEl1Mq2xaknL359CvfZr7iL_u7fcg6vgaHzpL-rcktPuYGkr6gT9xczh1FHhuOP0zc3r_tZhyphenhyphenenMekVdpIkz9r-2M/s1600/explosion.png" height="193" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
En el vídeo se puede apreciar al completo la nueva <b>animación de impacto</b> y el <b>parpadeo</b> tras el contacto con proyectiles enemigos.</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen="" frameborder="0" height="283" src="https://www.youtube.com/embed/6TpQePGeezY" width="504"></iframe>
</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
También se han realizado algunos cambios menores de diseño, como <b>separar las piernas</b> a <b>Rocket Man</b>.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxHPv6jwGlVVzpkOVnYfuvalNsZIowXMIhvsVRrI55IxAfGjN15lBXehhjp2JdvRHsmT8mlL-IJMyVqggh3jPwv9gme24sLj6r5xBoPye7N0Y7NDVZsx8ccZ_Aczc81Q037BmBydhEx50/s1600/cambios.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxHPv6jwGlVVzpkOVnYfuvalNsZIowXMIhvsVRrI55IxAfGjN15lBXehhjp2JdvRHsmT8mlL-IJMyVqggh3jPwv9gme24sLj6r5xBoPye7N0Y7NDVZsx8ccZ_Aczc81Q037BmBydhEx50/s1600/cambios.png" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
Imanoleahttp://www.blogger.com/profile/03989722316939496203noreply@blogger.com0tag:blogger.com,1999:blog-2099766654099311467.post-65440111432961250332015-02-01T20:00:00.001+01:002015-02-01T20:01:33.260+01:00Rocket Man #9: Enemigos III (Muerte)<div>
El juego cuenta con un<b> nuevo enemigo</b>. Su diseño gráfico está finalizado aunque su <b>comportamiento</b> aún se encuentra <b>en desarrollo</b>,</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0hndU3DX6wWRgP3C79H7uR2Af5gS9fxUM1Peq07wI3no6tFw9F_msyBuB7IfhAE5SXJM5gXw7BxpYtl1x0s5rUg5Ny8fSW7-s6khpO-PrM7iAO-PXNO4LjDbvj0lrVYrDnPG4gvB1gak/s1600/diamondEnemy.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0hndU3DX6wWRgP3C79H7uR2Af5gS9fxUM1Peq07wI3no6tFw9F_msyBuB7IfhAE5SXJM5gXw7BxpYtl1x0s5rUg5Ny8fSW7-s6khpO-PrM7iAO-PXNO4LjDbvj0lrVYrDnPG4gvB1gak/s1600/diamondEnemy.png" height="200" width="200" /></a></div>
<div>
<br /></div>
<div>
Como avance principal, los <b>enemigos</b> cuentan con <b>puntos de salud</b> y <b>explotan </b>cuando estos se agotan. De manera excepcional, el vídeo de la actualización se trata de una <b>grabación sobre el hardware real</b>. Este vídeo tiene el objetivo de aclarar que el <b>funcionamiento </b>que se va mostrando a lo largo del desarrollo es el <b>mismo</b> que se mostraría en la <b>Game Boy</b>.</div>
<div>
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/5Ti-ziTMU3c" width="420"></iframe>
</div>
<div>
<div style="text-align: center;">
<br /></div>
</div>
Entre algunos cambios menores se encuentra la <b>reducción de tamaño </b>de los <b>barriles</b>.<br />
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj13Az_Nv5hozDvJ5PKSE9v3yX_6CpjTFpHYlBxeJFiPkTHQO5rfkrYeQkgCkAAtWh9vjfDCgt16x8kTTdTZPL1JWbvRJj-DgAuh2lRy0LolxgRRRrHxcdSlSWoKOpRffkRoW8njOF1QT0/s1600/barriles.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj13Az_Nv5hozDvJ5PKSE9v3yX_6CpjTFpHYlBxeJFiPkTHQO5rfkrYeQkgCkAAtWh9vjfDCgt16x8kTTdTZPL1JWbvRJj-DgAuh2lRy0LolxgRRRrHxcdSlSWoKOpRffkRoW8njOF1QT0/s1600/barriles.png" height="160" width="320" /></a></div>
<div>
<br /></div>
Imanoleahttp://www.blogger.com/profile/03989722316939496203noreply@blogger.com1tag:blogger.com,1999:blog-2099766654099311467.post-6040271924714414562015-01-25T18:34:00.001+01:002022-10-15T21:41:29.962+02:00No more room in Limbo (Global Game Jam 2015)Videojuego creado en 48 horas para la Global Game Jam 2015 en Edificio Universidad Mondragon.<br />
<div style="text-align: center;">
<div style="text-align: left;">
<div style="text-align: center;">
<br /></div>
</div>
</div>
<div style="text-align: center;">
<div style="text-align: left;">
<div style="text-align: center;">
<iframe allowfullscreen="" frameborder="0" height="300" src="//www.youtube.com/embed/P8N02l1ApeE" width="510"></iframe>
</div>
</div>
</div>
<div style="text-align: center;">
<div style="text-align: left;">
<div style="text-align: center;">
<b><br /></b></div>
</div>
</div>
<div style="text-align: left;">
<div style="text-align: center;">
<div style="text-align: left;">
<b>Equipo de Desarrollo:</b> Unai Alonso, Imanol Barriuso, Gaizka Lombera.</div>
</div>
</div>
<br />
<b>Plataforma:</b> PC.<br />
<b>Fecha de Finalización: </b>25 de enero de 2015.<br />
<br />
<b>Género:</b> Aventura.<br />
<br />
<b>Juego:</b> <a href="https://drive.google.com/drive/folders/1BL81sBnuxGyhmTCjGys1IyTxuLuLnFQy?usp=sharing">Descarga</a>Imanoleahttp://www.blogger.com/profile/03989722316939496203noreply@blogger.com0tag:blogger.com,1999:blog-2099766654099311467.post-20017524714237282812015-01-10T15:36:00.000+01:002015-01-12T14:55:08.178+01:00Rocket Man #8: Arte oficial I<div class="separator" style="clear: both; text-align: left;">
El juego ya cuenta con un <b>primer arte</b>. Arte realizado por mi padre <b>Teo Barriuso</b>, con el que ya colaboré para realizar la pantalla de carga de <a href="http://imanoleasgames.blogspot.com.es/2014/02/the-subject.html"><b>The Subject</b></a> para <b>ZX Spectrum</b>.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXQpIyyT6SW3E6WsYqLhrdPcx-UQbI0s_Wbp7tg599Gha5R_DZhVDk2RbBrd3Diyd8a5SccyhIavrglY5W_xuvYZNJhfAN2xKiNYd219R3vywz3ckwNFX-cJymrpEWgTwMTS50OVymquU/s1600/RocketMan-Original.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXQpIyyT6SW3E6WsYqLhrdPcx-UQbI0s_Wbp7tg599Gha5R_DZhVDk2RbBrd3Diyd8a5SccyhIavrglY5W_xuvYZNJhfAN2xKiNYd219R3vywz3ckwNFX-cJymrpEWgTwMTS50OVymquU/s1600/RocketMan-Original.png" height="320" width="318" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div style="text-align: center;">
<span style="font-size: x-small;">Rocket Man en acción</span></div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: left;">
También se ha <b>modificado </b>ligeramente el cohete del <b>sprite</b> de <b>Rocket Man</b> en el juego, en busca de la homogeneidad con el material.</div>
<div style="text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizVhlW8bEdMumiuQZw2r-gAmmu0CifgdOLHl_iwaxkcXWLyAqTd1-wRnFkAsBt4l0ol6lsHhflh8O2r34zQs6E5z8B4hfFCtSbXlKV1p-cD36ewQtQyfsmYd-s_ONaT4aUTpopq2NkkwA/s1600/Comparativa.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizVhlW8bEdMumiuQZw2r-gAmmu0CifgdOLHl_iwaxkcXWLyAqTd1-wRnFkAsBt4l0ol6lsHhflh8O2r34zQs6E5z8B4hfFCtSbXlKV1p-cD36ewQtQyfsmYd-s_ONaT4aUTpopq2NkkwA/s1600/Comparativa.png" height="160" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Imanoleahttp://www.blogger.com/profile/03989722316939496203noreply@blogger.com0tag:blogger.com,1999:blog-2099766654099311467.post-40907061997618823292014-12-05T15:17:00.001+01:002015-01-12T14:55:08.188+01:00Rocket Man #7: Enemigos II (Comportamiento)En esta segunda fase se le ha añadido al primer tipo de enemigo una <b>animación de disparo</b>,<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1hTsp6WjLLphbE4-o1UYg6NOkHO8obbhac94fV23DCx6ENz_XOSFgz_-NGk0dK4uLwcLNG_ipaSqsUNC9sXpXioG4CsWrF8LXPa0LOw3khxgiUTW77bqZPRK95dub1dM0GsThdhA21aA/s1600/disparo.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1hTsp6WjLLphbE4-o1UYg6NOkHO8obbhac94fV23DCx6ENz_XOSFgz_-NGk0dK4uLwcLNG_ipaSqsUNC9sXpXioG4CsWrF8LXPa0LOw3khxgiUTW77bqZPRK95dub1dM0GsThdhA21aA/s1600/disparo.png" height="171" width="320" /></a></div>
<br />
<br />
También se ha implementado una <b>IA</b> simple que provoca que el <b>enemigo apunte en la dirección de Rocket Man</b>.<br />
<br />
Además de eso, <b>Rocket Man</b> cuenta con una nueva <b>animación</b> <b>de aparición</b> que se produce al <b>inicial el nivel</b>.<br />
<br />
<div style="text-align: center;">
<iframe allowfullscreen="" frameborder="0" height="315" src="//www.youtube.com/embed/43l-ZfUsVnc" width="420"></iframe>
</div>
<div style="text-align: center;">
<br /></div>
Imanoleahttp://www.blogger.com/profile/03989722316939496203noreply@blogger.com0tag:blogger.com,1999:blog-2099766654099311467.post-28884332929575329332014-11-18T11:01:00.001+01:002015-01-12T15:12:24.876+01:00Rocket Man #6: Enemigos I (Generación)El <b>primer enemigo</b> aparece en escena,<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPCidX2mHUqP87T7Cg_aOOacMbys7SlwMLX1vOOOclHA9TdGVJs2HXquHundQyxphRqwuRupd5PuCVHOb8dyfOfnDvPYrtiON_UoLZpJrmdbWgmaHiGeY1wQRDdTEkGYfXX6xBfOiVamw/s1600/GunGuard.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPCidX2mHUqP87T7Cg_aOOacMbys7SlwMLX1vOOOclHA9TdGVJs2HXquHundQyxphRqwuRupd5PuCVHOb8dyfOfnDvPYrtiON_UoLZpJrmdbWgmaHiGeY1wQRDdTEkGYfXX6xBfOiVamw/s1600/GunGuard.png" /></a></div>
<br />
<div style="text-align: center;">
<div style="text-align: left;">
Tomando este enemigo como base se ha diseñado un sistema de <b>generación de enemigos</b> a lo largo del mapa en <b>posiciones específicas</b>.</div>
</div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen="" frameborder="0" height="315" src="//www.youtube.com/embed/souCCwxSCEs" width="420"></iframe>
</div>
<div style="text-align: center;">
<br /></div>
Imanoleahttp://www.blogger.com/profile/03989722316939496203noreply@blogger.com0