あのゲームとりあえず完成

あのゲーム、とりあえず完成。

コードは本に書かれてたものを多少流用した。

あんま光らせ過ぎるとまずいかなと思って、
横は6列までしか使っていない。

しかしまぁ、コードはだいぶ適当に書いててひどいんだけど

ここで先人の言葉を借りることにしよう。

Done is better than perfect.

参考にしたのはこの本。

コードはこんな感じ。


import RPi.GPIO as GPIO, time
import subprocess, random
from subprocess import Popen

proc = Popen(["mpg321", "bgm.mp3"])

GPIO.setmode(GPIO.BCM)
GPIO.setup(12, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(25, GPIO.IN, pull_up_down=GPIO.PUD_UP)

# 割り込みハンドラ 左移動
def go_left(*arg):
	global x
	global y
	global rotation
	global obj_type
	global matrix
	global can_interrupt

	if (can_interrupt):
		clear_obj(x, y, rotation, obj_type, matrix)
		x -= 1
		if (check_overlap(x, y, rotation, obj_type, matrix)):
			x += 1
		write_obj(x, y, rotation, obj_type, matrix)

# 割り込みハンドラ 右移動
def go_right(*arg):
	global x
	global y
	global rotation
	global obj_type
	global matrix
	global can_interrupt
	
	if (can_interrupt):
		clear_obj(x, y, rotation, obj_type, matrix)
		x += 1
		if (check_overlap(x, y, rotation, obj_type, matrix)):
			x -= 1
		write_obj(x, y, rotation, obj_type, matrix)

# 割り込みハンドラ 回転
def turn(*arg):
	global x
	global y
	global rotation
	global obj_type
	global matrix
	global can_interrupt

	if (can_interrupt):
		prev_rotation = rotation
		clear_obj(x, y, rotation, obj_type, matrix)
		rotation = (rotation + 1) % 4
		if (check_overlap(x, y, rotation, obj_type, matrix)):
			rotation = prev_rotation
		write_obj(x, y, rotation, obj_type, matrix)

GPIO.add_event_detect(12, GPIO.FALLING, callback=go_left,  bouncetime=140)
GPIO.add_event_detect(25, GPIO.FALLING, callback=go_right, bouncetime=140)
GPIO.add_event_detect(24, GPIO.FALLING, callback=turn,     bouncetime=140)

# GPIO LEDpin anode_side
#   21      9
#   16     14
#   23      8
#   20     12
#    4      1
#   22      7
#   17      2
#   27      5
anode = [21,16,23,20,4,22,17,27]

# GPIO LEDpin cathode_side
#   13     13
#   14      3
#   15      4
#    5     10
#   18      6
#    6     11
#   19     15
#   26     16
cathode = [13,14,15,5,18,6,19,26]

for i in anode:
	GPIO.setup(i, GPIO.OUT)
	GPIO.output(i, GPIO.LOW)
for i in cathode:
	GPIO.setup(i, GPIO.OUT)
	GPIO.output(i, GPIO.HIGH)

def obj_calc(x, y, rotation, obj_type):
	# ブロックの形6種類
	form_type = [[ 0, -1,  0,  1,  0, 2],
                     [-1, -1,  0, -1,  0, 1],
                     [ 0, -1, -1,  0,  0, 1],
                     [ 0, -1, -1,  1,  0, 1],
                     [ 0,  1,  1,  0,  1, 1],
                     [ 0,  1,  1, -1,  1, 0]]
	return_obj = []

	obj = form_type[obj_type]
	count = 0
	while count < 3:
		relative_y = obj[count*2 + 0]
		relative_x = obj[count*2 + 1]
		rotate_times = 0
		while rotate_times < rotation:
			tmp = relative_y
			relative_y = relative_x
			relative_x = tmp
			relative_x = -relative_x
			rotate_times += 1

		return_obj.append(x + relative_x)
		return_obj.append(y + relative_y)
		count += 1

	return return_obj

def write_obj(x, y, rotation, obj_type, matrix):

	x2,y2,x3,y3,x4,y4 = tuple(obj_calc(x,y,rotation,obj_type))

	matrix[y][x]   = 1
	matrix[y2][x2] = 1
	matrix[y3][x3] = 1
	matrix[y4][x4] = 1

def clear_obj(x, y, rotation, obj_type, matrix):

	x2,y2,x3,y3,x4,y4 = tuple(obj_calc(x,y,rotation,obj_type))

	matrix[y][x]   = 0
	matrix[y2][x2] = 0
	matrix[y3][x3] = 0
	matrix[y4][x4] = 0

def check_overlap(x, y, rotation, obj_type, matrix):

	x2,y2,x3,y3,x4,y4 = tuple(obj_calc(x,y,rotation,obj_type))

	if (matrix[y][x]   == 1 or
            matrix[y2][x2] == 1 or
            matrix[y3][x3] == 1 or
            matrix[y4][x4] == 1   ):
		return True
        else:
                return False


# 落下スピードを返す関数
def speed_calc(matrix):
	speed = 0
	gleaming_led = 0

	# 光るLEDの個数を数える
	for i in range(1,9):
		for j in range(1,7):
			if(matrix[i][j] == 1):
				gleaming_led += 1
	if(gleaming_led < 6):
		speed = 2550
	elif(gleaming_led < 10):
		speed = 2250
	elif(gleaming_led < 15):
		speed = 1850
	else:
		speed = 1600

	return speed


# ラインが揃ってたら消す関数
def clear_line(matrix):
	del_index_list = []
	for i in range(1,9):
		if(matrix[i].count(1) == 8):
			del_index_list.append(i)
	length = len(del_index_list)
	if(length > 0):
		del_index_list.reverse()
		for i in del_index_list:
			del matrix[i]
		for i in range(length):
			matrix.insert(1,[1,0,0,0,0,0,0,1])


# 2次元表を90度右に回転させる関数
def change_deg(matrix):
	changed_matrix = []
	tmp = []

	for xi in range(1,7):
		for yi in range(8,0,-1):
			tmp.append(matrix[yi][xi])
		changed_matrix.append(tmp)
		tmp = []

	return changed_matrix

x = 4
y = 1
rotation = 0
can_interrupt = True
matrix = [
	[0,0,0,0,0,0,0,0],
	[1,0,0,0,0,0,0,1],
	[1,0,0,0,0,0,0,1],
	[1,0,0,0,0,0,0,1],
	[1,0,0,0,0,0,0,1],
	[1,0,0,0,0,0,0,1],
	[1,0,0,0,0,0,0,1],
	[1,0,0,0,0,0,0,1],
	[1,0,0,0,0,0,0,1],
	[1,1,1,1,1,1,1,1]
]

try:
	obj_type = random.randint(0,5)
	write_obj(x, y, rotation, obj_type, matrix)
	speed = speed_calc(matrix)
	count = 0
	while True:
		if (count > speed):                                             # 一定の速度で落下させる
			can_interrupt = False                                   # 落下中は割り込みさせない
			clear_obj(x, y, rotation, obj_type, matrix)             # ブロックを消す
			y += 1                                                  # 一個下に落ちる
			if (check_overlap(x, y, rotation, obj_type, matrix)):   # 重なりを調べる
				y -= 1                                            # 重なってたら戻す
				write_obj(x, y, rotation, obj_type, matrix)       # ブロックを書き込む
				clear_line(matrix)                                # ラインが揃ってたら消す

				x = 4                                             # また一番上から始める
				y = 1
				rotation = 0
				obj_type = random.randint(0,5)

				# if (check_overlap(x, y, rotation, obj_type, matrix)):   # スタート時点の重なりを調べる
				#	break                                           # 重なってたらゲームオーバー
				write_obj(x, y, rotation, obj_type, matrix)
			else:
				write_obj(x, y, rotation, obj_type, matrix)

			speed = speed_calc(matrix)
			count = 0
			can_interrupt = True

		changed_matrix = change_deg(matrix)
		# LED点滅部
		for i in range(6):
			for j in range(8):
				if(changed_matrix[i][j]):
					GPIO.output(anode[i],GPIO.HIGH)
					GPIO.output(cathode[j],GPIO.LOW)
					GPIO.output(anode[i],GPIO.LOW)
					GPIO.output(cathode[j],GPIO.HIGH)
		count += 1

except KeyboardInterrupt:
	GPIO.cleanup()

GPIO.cleanup()
proc.terminate()

スポンサーリンク
 
スポンサーリンク

コメントをどうぞ

メールアドレスが公開されることはありません。