Karoshi MSX Community
05 de Julio de 2021, 08:29:08 pm *
Bienvenido(a), Visitante. Por favor, ingresa o regístrate.

Ingresar con nombre de usuario, contraseña y duración de la sesión
Noticias:
 
   Inicio   Ayuda Buscar Ingresar Registrarse  
Páginas: [1]
  Imprimir  
Autor Tema: Conversor de sprites con bit CC  (Leído 4506 veces)
0 Usuarios y 1 Visitante están viendo este tema.
samsaga2
Karoshi Fan
**
Mensajes: 76


Email
« : 17 de Agosto de 2011, 10:18:45 am »

He estado intentando hacer un conversor de sprites que tenga en cuenta el modo mixto de los msx 2 (al puro estilo sprite converter http://www.msx.org/modules.php?op=modload&name=Downloads&file=index&req=visit&lid=305). Pero por ahora lo único que consigo es un churro la mar de mono.

Teniendo una paleta preparada, ¿que algoritmo puedo usar para extraer los sprites usando el modo mixto?
En línea
SapphiRe_MSX
Visitante
« Respuesta #1 : 17 de Agosto de 2011, 10:59:07 pm »

Supongamos que son sprites de dos planos, si fueran más las ecuaciones se complicarían un poquito, pero teniendo la paleta ya preparada y fijada no es muy problemático. Por cada línea del sprite, tenemos que los colores han de satisfacer una ecuación del estilo:

(Color Sprite 0) OR (Color Sprite 1) = (Color Mezcla)

Tienes que analizar en cada línea qué colores hay y si satisfacen esa ecuación, pero como la paleta es fija, puedes probar todas las posibles combinaciones de colores (realmente sólo hay 3). Supongamos que encuentras tres colores (aparte del transparente) digamos A, B y C. Entonces:

-Si A OR B = C, para el sprite 0 ponemos el A y para el 1 el B (o viceversa)
-Si A OR C = B, para el sprite 0 ponemos el A y para el 1 el C (o viceversa)
-Si B OR C = A, para el sprite 0 ponemos el B y para el 1 el C (o viceversa)

Si los colores de esa línea no satisfacen ninguna de las ecuaciones, entonces no se puede convertir en un sprite multicolor de 2 planos. Ojo, esto es porque tienes la paleta fija. Si tuvieras que moverla, entonces la cosa se complicaría un poco, porque habría que crear un sistema con las 16 ecuaciones que obtendríamos por todas las líneas del sprite y resolver el sistema (si es que es posible, claro).

Supongamos que los colores satisfacen la ecuación. Entonces nos fijamos en la posición de los colores en la línea y si nos encontramos:

-Un pixel transparente: se traduce en un bit 0 para ambos sprites
-Un pixel del color para el sprite 0: se traduce en un bit 1 para el sprite 0 y en un bit 0 para el sprite 1.
-Un pixel del color para el sprite 1: se traduce en un bit 0 para el sprite 1 y en un bit 1 para el sprite 0.
-Un pixel del color mezclado: se traduce en un bit 1 para ambos sprites

De esta forma tienes ya la línea de los dos sprites y su color. Repitiendo el procedimiento para todas las líneas, tendrás el sprite completo.

Espero que esto te sirva.
En línea
samsaga2
Karoshi Fan
**
Mensajes: 76


Email
« Respuesta #2 : 18 de Agosto de 2011, 08:08:22 am »

Genial, lo probaré como dices. Os mantendré informados. Colgaré el script en perl cuando lo tenga funcionando.
En línea
samsaga2
Karoshi Fan
**
Mensajes: 76


Email
« Respuesta #3 : 20 de Agosto de 2011, 03:29:11 pm »

Ha funcionado a la perfección. Aujnque sólo soporta un máximo de dos sprites no creo que nadie use más con el modo mixto.

Es un script en perl. Os lo adjunto por si le puede ser de utilidad a alguien:

Código:
use strict;
use warnings;
use Image::Magick;
use List::MoreUtils qw/ uniq /;

sub bin2dec {
return unpack("N", pack("B32", substr("0" x 32 . shift, -32)));
}

sub extract_pattern {
my ($row) = @_;
 
my @colors = sort {$a<=>$b} grep {$_} uniq @{$row};
my $color_a = shift @colors;
my $color_b = shift @colors;
my $color_c = shift @colors;

die "Too many colors." if $#colors >= 0;

if(defined $color_c) {
if(($color_b | $color_c) == $color_a) {
($color_a, $color_c) = ($color_c, $color_a);
} elsif(($color_a | $color_c) == $color_b) {
($color_b, $color_c) = ($color_c, $color_b);
} elsif(($color_a | $color_b) != $color_c) {
die "Wrong row colors.";
}
}

my @layers = ();
my $cc = defined $color_c ? 64 : 0;

my @bits0 = map {defined $color_a && $_ == $color_a || defined $color_c && $_ == $color_c ? 1 : 0} @{$row};
push @layers, [\@bits0, $color_a];

if (defined $color_b) {
my @bits1 = map {$_ == $color_b || defined $color_c && $_ == $color_c ? 1 : 0} @{$row};
push @layers, [\@bits1, ($color_b | $cc)];
}

return \@layers;
}

sub export_sprite {
my ($image, $tx, $ty) = @_;

my @sprite0 = ();
my @sprite1 = ();

foreach my $y (0..15) {
my $oy = $ty + $y;

my @row = ();
foreach my $x (0..15) {
my $ox = $tx + $x;
$row[$x] = $image->[0]->Get("Index[$ox,$oy]");
}

my $layers = extract_pattern \@row;
$sprite0[$y] = $layers->[0];
$sprite1[$y] = $layers->[1] if $layers->[1];
}

my @sprites = (\@sprite0, \@sprite1);
return \@sprites;
}

sub print_sprite_patterns {
my ($sprite, $file) = @_;

foreach my $column (0..1) {
foreach my $y (0..15) {
my $row = $sprite->[$y]->[0];
my $bits = '';
$bits .= $row->[$column * 8 + $_]||0 for(0..7);
my $byte = bin2dec($bits);
print $file "db $byte\t; B:$bits R:$y\n";
}
}
}

sub print_sprite_colors {
my ($sprite, $file) = @_;

foreach my $y (0..15) {
my $byte = $sprite->[$y]->[1] || 0;
my $color = $byte & 15;
my $cc = $byte & 64 ? 1 : 0;
print $file "db $byte\t; C:$color CC:$cc R:$y\n";
}
}

sub export_sprites {
my ($filename, $out_pattern, $out_color) = @_;

# read image
my $image = Image::Magick->new;
$image->Read($filename);

# image size
my $width = $image->Get("width");
my $height = $image->Get("height");

if($width % 16 || $height % 16) {
die "Wrong image size: $width x $height. Must be multiple of 16x16.\n";
}

open OUTPAT, ">$out_pattern" or die "Cannot create $out_pattern file.";
open OUTCOL, ">$out_color" or die "Cannot create $out_color file.";

# export sprites
my $sprites_qty = ($width / 16) * $height / 16;
my $x = 0;
my $y = 0;
for(my $i = 1; $i <= $sprites_qty; $i++) {
# extract sprite layers
my $sprites = export_sprite $image, $x, $y;

# write sprite
print OUTPAT "\t; sprite $i at ($x, $y) ------------\n";
print OUTCOL "\t; sprite $i at ($x, $y) ------------\n";
for my $layer_no (0..scalar @$sprites - 1) {
print OUTPAT "\t; layer $layer_no\n";
print_sprite_patterns $sprites->[$layer_no], *OUTPAT;

print OUTCOL "\t; layer $layer_no\n";
print_sprite_colors $sprites->[$layer_no], *OUTCOL;
}

# next sprite
$x += 16;
if($x == $width) {
$x = 0;
$y += 16;
}
}

close OUTPAT;
close OUTCOL;
}

if($#ARGV < 0) {
die "Missing filename.";
}

my $file_pat = $ARGV[1] || (split /\./, $ARGV[0])[0].".pat";
my $file_col = $ARGV[2] || (split /\./, $ARGV[0])[0].".col";
export_sprites $ARGV[0], $file_pat, $file_col;
En línea
SapphiRe_MSX
Visitante
« Respuesta #4 : 20 de Agosto de 2011, 06:45:57 pm »

Ha funcionado a la perfección. Aujnque sólo soporta un máximo de dos sprites no creo que nadie use más con el modo mixto.

¡Genial! Yo lo que quiero es hacer algo parecido, pero que permita reordenar la paleta si es necesario. Será mi primer proyecto en Java, ya que tengo que aprender ese lenguaje.

¡¡Gracias por compartir código!!
En línea
samsaga2
Karoshi Fan
**
Mensajes: 76


Email
« Respuesta #5 : 21 de Agosto de 2011, 07:54:31 am »

¿Como lo vas ha hacer para reordenar la paleta? Ahora mismo sólo se me ocurre probar todas las combinaciones posibles (que con 16 colores no son demasiadas).
En línea
MsxKun
Karoshi Forum's Guru
*******
Mensajes: 1554


Kimochi-ii


WWW Email
« Respuesta #6 : 21 de Agosto de 2011, 10:28:55 am »

Ha funcionado a la perfección. Aujnque sólo soporta un máximo de dos sprites no creo que nadie use más con el modo mixto.

Jiejie  Grin Crees mal... En el personaje de mi nuevo juego junto 3 sprites con el fin de tener 5 colores (que podrian ser 6 si quisiera).  Evil
En línea

--

Cindy Lauper She Bops!
SapphiRe_MSX
Visitante
« Respuesta #7 : 21 de Agosto de 2011, 11:40:48 pm »

Jiejie  Grin Crees mal... En el personaje de mi nuevo juego junto 3 sprites con el fin de tener 5 colores (que podrian ser 6 si quisiera).  Evil

De hecho podrían ser 7 colores por línea Cheesy
En línea
samsaga2
Karoshi Fan
**
Mensajes: 76


Email
« Respuesta #8 : 23 de Agosto de 2011, 06:51:19 am »

Ha funcionado a la perfección. Aujnque sólo soporta un máximo de dos sprites no creo que nadie use más con el modo mixto.

Jiejie  Grin Crees mal... En el personaje de mi nuevo juego junto 3 sprites con el fin de tener 5 colores (que podrian ser 6 si quisiera).  Evil

Esa paleta de colores debe dar dolores de cabeza  Griel

Si alguien usa el conversor y cree que le será útil que soporte más de dos sprites para el color mixto que me lo diga, ya que creo que se me ha ocurrido una forma de hacerlo.
En línea
SapphiRe_MSX
Visitante
« Respuesta #9 : 23 de Agosto de 2011, 08:19:04 am »

¿Como lo vas ha hacer para reordenar la paleta? Ahora mismo sólo se me ocurre probar todas las combinaciones posibles (que con 16 colores no son demasiadas).

Pues son demasiadas, concretamente 20.922.789.888.000, ¡casi na! La idea sería hacer lo mismo que te indiqué, pero como no sabemos la paleta de colores, antes de analizar los colores de cada línea habría que encontrar un sistema de ecuaciones que fuese compatible.

Posiblemente con una estrategia de análisis de grafos tipo backtracking podría encontrarse una respuesta en un tiempo bastante razonable. Tendré que echarle una pensada al tema y a ver si saco un prototipo de algoritmo en haskell.
En línea
MsxKun
Karoshi Forum's Guru
*******
Mensajes: 1554


Kimochi-ii


WWW Email
« Respuesta #10 : 23 de Agosto de 2011, 10:49:06 am »

Ha funcionado a la perfección. Aujnque sólo soporta un máximo de dos sprites no creo que nadie use más con el modo mixto.

Jiejie  Grin Crees mal... En el personaje de mi nuevo juego junto 3 sprites con el fin de tener 5 colores (que podrian ser 6 si quisiera).  Evil

Esa paleta de colores debe dar dolores de cabeza  Griel

Que va, solo es controlar 5 colores antes de hacer nada y tenerlo claro. A veces la forma menos complicada de hacer las cosas es, efectivamente, la menos complicada Tongue
En línea

--

Cindy Lauper She Bops!
Páginas: [1]
  Imprimir  
 
Ir a:  

Impulsado por MySQL Impulsado por PHP Powered by SMF 1.1.21 | SMF © 2013, Simple Machines XHTML 1.0 válido! CSS válido!