RetroAvatarsをHSPに移植する(3)

前回:RetroAvatarsをHSPに移植する(2)
だいたいできた。

  • メイン処理は最後まで書いた。
  • floodFillの勘違いⅡを修正。
  • しっかりモジュール化。
  • 入力部分はまだない。



真・TANINI。前回とは似ても似つかぬほどになった。

途中経過(383行)

#define global W 12
#define global H 12
#define global PW 12
#define global PH 12
#define global EMPTY_COL 0
#define global SOLID_COL 255
#define global EYES_COL 1
#define global NOSE_COL 2
#define global MOUTH_COL 3
#define global WORK_COL 4
#define global MARGIN 30


#module retroAvatars

// 画像の初期化
#deffunc init str name, local x, local y
	screen 0, 12*10+MARGIN*2, 12*10+MARGIN*2

	titleStr = name
	size = strlen(titleStr)

	title titleStr

	code = 0
	randomize(0)
	repeat 32
		code = code + (peek(titleStr,cnt\size)*rnd(32768)\1024)
	loop

	randomize(code)
	col_r = rnd(32768)\192 + 64
	col_g = rnd(32768)\192 + 64
	col_b = rnd(32768)\192 + 64

	dim g, 14, 14
	for y, 0, 14, 1
		for x, 0, 14, 1
			g.y.x = -1
		next
	next

	for y, 1, H+1, 1
		for x, 1, W+1, 1
			c = 158
			if( rnd(32768)\356 > c ){
				g.y.x = EMPTY_COL
			} else {
				g.y.x = SOLID_COL
			}
		next
	next

	return


// 孤立したピクセルを除去
#deffunc removeNoise int type, local x, local y
	repeat 4
		for y, 1, H+1, 1
			for x, 1, W+1, 1
				if( g.y.x == EMPTY_COL ){
					x1 = x-1 : x2 = x+1 : y1 = y-1 : y2 = y+1
					p = g.y1.x1 + g.y1.x + g.y1.x2 + g.y.x1 + g.y.x2 + g.y2.x1 + g.y2.x + g.y2.x2
					if( ( type == 0 )&&( p >= SOLID_COL*8 ) ) : g.y.x = SOLID_COL
					if( ( type == 1 )&&( p >= SOLID_COL*7 ) ) : g.y.x = SOLID_COL

					if( ( g.y1.x == SOLID_COL )&&( g.y2.x == SOLID_COL ) ){
						if( ( g.y.x1 != SOLID_COL )&&(g.y.x2 != SOLID_COL ) ){
								if ( rnd(32768)\5 > 2 ) : g.y.x = SOLID_COL
						}
					}
					if( ( g.y1.x != SOLID_COL )&&( g.y2.x != SOLID_COL ) ){
						if( ( g.y.x1 == SOLID_COL )&&( g.y.x2 == SOLID_COL ) ){
								if ( rnd(32768)\5 > 2 ) : g.y.x = SOLID_COL
						}
					}
				}
			next
		next

		dim xt, 8 : dim yt, 8
		xt = -1, 0, 1, -1, 1, -1, 0, 1
		yt = -1, -1, -1, 0, 0, 1, 1, 1
		for y, 1, H+1, 1
			for x, 1, W+1, 1
				if( g.y.x == SOLID_COL ){
					p = 0
					for i, 0, 8, 1
						y0 = y+yt.i : x0 = x+xt.i
						p += g.y0.x0
					next
					if( p <= 0 ) : g.y.x = EMPTY_COL
				}
			next
		next
	loop
	return


//反転
#deffunc mirror local x, local y
	x_sym = 1
	y_sym = 0

	for y, 1, H+1, 1
		for x, 1, W/2+1, 1
			p = g.y.x
			if( x_sym == 1 ){
				x0 = W-x+1
				g.y.x0 = p
			}
		next
	next

	for y, 1, H/2+1, 1
		for x, 1, W+1, 1
			p = g.y.x
			if( y_sym == 1 ){
				y0 = H-y+1
				g.y0.x = p
			}
		next
	next
	return


#defcfunc checkForFilledEdge local x, local y
	for y, 1, H+1, 1
		if( ( EMPTY_COL < g.y.1 )&&( g.y.1 < SOLID_COL ) ) : return 1
		if( ( EMPTY_COL < g.y.W )&&( g.y.W < SOLID_COL ) ) : return 1
	next
	for x, 1, W+1, 1
		if( ( EMPTY_COL < g.1.x )&&( g.1.x < SOLID_COL ) ) : return 2
		if( ( EMPTY_COL < g.H.x )&&( g.H.x < SOLID_COL ) ) : return 2
	next
	return 0


#deffunc outlineArea int col, local x, local y
	dim xt, 8 : dim yt, 8
	xt = 0, 1, 0, -1, -1, 1, -1, 1
	yt = -1, 0, 1, 0, -1, -1, 1, 1

	for y, 1, H+1, 1
		for x, 1, W+1, 1
			if( g.y.x == col ){
				for i, 0, 8, 1
					y0 = y+yt.i : x0 = x+xt.i
					if( i < 4 ){
						if( g.y0.x0 != col ) : g.y0.x0 = SOLID_COL
					} else {
						if( g.y0.x0 == EMPTY_COL ) : g.y0.x0 = SOLID_COL
					}
				next
			}
		next
	next
	return


// 塗りつぶし
#deffunc floodFill int startX, int startY, int col, local x, local y
	p = g.startY.startX
	g.startY.startX = col

	dim xt, 4 : dim yt, 4
		xt = 0, 1, 0, -1
		yt = -1, 0, 1, 0
	for i, 0, 4, 1
		x = startX + xt.i : y = startY + yt.i
		if( (1 <= x )&&( x <= W ) ){
			if( ( 1 <= y )&&( y <= H ) ){
				if( g.y.x == p ) : floodFill x, y, col
			}
		}
	next
	return


#deffunc trimArea int col, int _w, int _h, local x, local y
	nx = -1 : ny = -1
	for y, 1, H+1, 1
		for x, 1, W/2+1, 1
			if( col == EYES_COL ) : rx = x
			if( col > EYES_COL ) : rx = w/2 - x

			p = g.y.rx
			if( p == col ){
				if( nx == -1 ) : nx = x
				if( ny == -1 ) : ny = y
				if( x >= nx + _w ) : g.y.rx = SOLID_COL
				if( y >= ny + _h ) : g.y.rx = SOLID_COL
			}
		next
	next
	return


#deffunc enhanceFace local x, local y
	hx = W/2
	eyes = 0 : nose = 0 : mouth = 0

	for y, 2, H/2+1,1
		x0 = hx-1
		if( g.y.x0 == EMPTY_COL ){
			floodFill x0, y, EYES_COL
			if( checkForFilledEdge() == 0 ) : _break
			floodFill x0, y, EMPTY_COL
		}

		x0 = hx-2
		if( g.y.x0 == EMPTY_COL ){
			floodFill x0, y, EYES_COL
			if(  checkForFilledEdge() == 0 ) : _break
			floodFill x0, y, EMPTY_COL
		}
	next


	if( y == H/2+1 ){
		for y, 2, H+1, 1
			x0 = hx-1
			if( g.y.x0 == SOLID_COL ){
				if( g.y.hx == EMPTY_COL ){
					g.y.x0 = EMPTY_COL
					g.y.hx = SOLID_COL
					y0 = y+1
					g.y0.x0 = EMPTY_COL

					floodFill x0, y, EYES_COL
					if( checkForFilledEdge() == 0 ) : _break
					floodFill x0, y, EMPTY_COL
				}
			}
		next
	}


	ny = y + 1
	if( y <= H ) : eyes = 1

	if( eyes == 0 ){
			y = 2 + rnd(32768)\(h/2)
			x0 = hx-1
			g.y.x0 = EYES_COL
			outlineArea g, EYES_COL
			eyes = 1
			ny = y + 1
	}

	for y, 2, H+1, 1
		if( g.y.hx == EYES_COL ){
			x0 = hx-1
			g.y.hx = SOLID_COL
			g.y.x0 = EYES_COL
		} else {
			x0 = hx-2
			if( g.y.x0 == EYES_COL ) : g.y.hx = SOLID_COL
			x0 = hx-1
			if( g.y.x0 == EYES_COL ) : g.y.hx = SOLID_COL
		}
	next
	mirror
	if( eyes == 1 ) : outlineArea 1

	// 鼻
	for y, ny, H+1, 1
		if( g.y.hx == EMPTY_COL ){
			floodFill hx, y, NOSE_COL
			if( checkForFilledEdge() == 0 ) : _break
			floodFill hx, y, EMPTY_COL
		}
	next
	if( y <= 10 ) : nose = 1

	if( nose == 0 ){
		for y, ny, H, 1
			if( g.y.hx == EMPTY_COL ){
				g.y.hx = NOSE_COL
				nose = 1
				goto *skip
			}
		next

		for y, ny, H, 1
			x0 = hx-1
			if( g.y.x0 == EMPTY_COL ){
				g.y.x0 = NOSE_COL
				g.y.hx = NOSE_COL
				nose = 1
				goto *skip
			}
		next

		y = ny + 1 + rnd(32768)\(h/3)
		if( y >= H ) : y = H-1

		g.y.hx = NOSE_COL
		nose = 1
		ny = y + 1
		goto *skip
	}

	ny = y + 1

	//口
	for y, ny, H+1, 1
		if( g.y.hx == EMPTY_COL ){
			floodFill hx, y, MOUTH_COL
			if( checkForFilledEdge() == 0 ) : _break
			floodFill hx, y, EMPTY_COL
		}
	next
	if( y <= H ) : mouth = 1

	if( mouth == 0 ){
		for y, ny, H, 1
			x0 = hx-1
			if( g.y.x0 == EMPTY_COL ){
				g.y.hx = EMPTY_COL
				floodFill hx, y, MOUTH_COL
				if( checkForFilledEdge() == 0 ) : _break
				floodFill hx, y, EMPTY_COL
			}
		next
	}
	if( y <= H ) : mouth = 1

*skip
	if( mouth == 1 ) : outlineArea MOUTH_COL
	if( nose == 1 ) : outlineArea NOSE_COL

	if( eyes == 1 ) : trimArea EYES_COL, 3, 3
	if( nose == 1 && mouth == 1 ) : trimArea NOSE_COL, 3, 3
	mirror

	for y, 2, H, 1
		for x, 2, W, 1
			if( g.y.x == EMPTY_COL ){
				floodFill x, y, WORK_COL
				c = checkForFilledEdge()
				if( c != 0 ){
					floodFill x, y, EMPTY_COL
				} else {
					floodFill x, y, SOLID_COL
				}
			}
		next
	next

	return


//画像を表示
#deffunc draw local x, local y
	mirror
	color : boxf
	for y, 1, H+1, 1
		for x, 1, W+1, 1
			if( g.y.x == SOLID_COL ){
				color col_r, col_g, col_b
			} else {
				color 0, 0, 0
			}
			boxf MARGIN+(x-1)*10, MARGIN+(y-1)*10, MARGIN+(x-1)*10+10, MARGIN+(y-1)*10+10
		next
	next
	return


// 画像を生成(メイン)
#deffunc createGraph local x, local y
	init "TANINI"
	removeNoise 0
	enhanceFace
	draw
	return

#global


createGraph