foo
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
# fork of https://github.com/SmartViking/MaTris by deinkoks
|
||||
# removed everythin but elemental gameplay, added multiplayer controlled via mqtt
|
||||
# most ugly thing: a mqtt client for every player due to callback limitations
|
||||
@ -9,7 +9,7 @@ import os
|
||||
import paho.mqtt.client as mqtt
|
||||
|
||||
|
||||
from tetrominoes import list_of_tetrominoes
|
||||
from tetrominoes import list_of_tetrominoes, shape_str
|
||||
from tetrominoes import rotate
|
||||
|
||||
from scores import load_score, write_score
|
||||
@ -21,12 +21,16 @@ def get_sound(filename):
|
||||
return pygame.mixer.Sound(os.path.join(os.path.dirname(__file__), "resources", filename))
|
||||
|
||||
ENABLE_STDIO = True #dump game on stdio, not sure if works as intended.
|
||||
ENABLE_MQTT = True # for debugging w/o a broker
|
||||
ENABLE_SOUND = False
|
||||
ENABLE_KEYBOARD_CONTROLS = False # working for player1. mostly
|
||||
MQTT_TOPIC = "deckentetris/"
|
||||
|
||||
PLAYER = 10 # player count, 1 columns per player
|
||||
BGCOLOR = (15, 15, 20)
|
||||
BORDERCOLOR = (140, 140, 140)
|
||||
|
||||
BLOCKSIZE = 16 # set this to 1 if run on the pixeldecke
|
||||
GAMEOVER_COLOR = (140, 100, 100)
|
||||
BLOCKSIZE = 1 # set this to 1 if run on the pixeldecke
|
||||
BORDERWIDTH = 0
|
||||
|
||||
MATRIS_OFFSET = 0
|
||||
@ -34,14 +38,14 @@ MATRIS_OFFSET = 0
|
||||
# we have 8pixel columns with a height of 5*8px for every player
|
||||
# lets use one for the next block, but 2 lines are hidden
|
||||
MATRIX_WIDTH = 8
|
||||
MATRIX_HEIGHT = (4+2)*8
|
||||
MATRIX_HEIGHT = (4)*8
|
||||
|
||||
LEFT_MARGIN = 0
|
||||
|
||||
WIDTH = (MATRIX_WIDTH*BLOCKSIZE + MATRIS_OFFSET*2 + LEFT_MARGIN) * PLAYER
|
||||
HEIGHT = (MATRIX_HEIGHT-2)*BLOCKSIZE + MATRIS_OFFSET*2
|
||||
HEIGHT += BLOCKSIZE*8 # additional tile for preview above game
|
||||
|
||||
HEIGHT += 2 # height fix for reasons
|
||||
TRICKY_CENTERX = WIDTH-(WIDTH-(MATRIS_OFFSET+BLOCKSIZE*MATRIX_WIDTH))/2
|
||||
|
||||
VISIBLE_MATRIX_HEIGHT = MATRIX_HEIGHT - 2
|
||||
@ -60,22 +64,18 @@ class Matris(object):
|
||||
self.request_movement('left')
|
||||
elif payload == "right":
|
||||
self.request_movement('right')
|
||||
else:
|
||||
pass #print the matrix
|
||||
elif payload == "update":
|
||||
self.mqtt.publish(MQTT_TOPIC+str(offset)+"/current", payload=shape_str(self.current_tetromino.shape), qos=0, retain=False)
|
||||
self.mqtt.publish(MQTT_TOPIC+str(offset)+"/next", payload=shape_str(self.next_tetromino.shape), qos=0, retain=False)
|
||||
|
||||
def __init__(self, offset):
|
||||
self.surface = screen.subsurface(Rect((MATRIX_WIDTH * BLOCKSIZE*offset, 8*BLOCKSIZE),
|
||||
(MATRIX_WIDTH * BLOCKSIZE, (MATRIX_HEIGHT-2) * BLOCKSIZE)))
|
||||
self.mqtt = mqtt.Client()
|
||||
self.mqtt.connect("mqtt.chaospott.de", port=1883, keepalive=60, bind_address="")
|
||||
self.offset = offset
|
||||
self.matrix = dict()
|
||||
for y in range(MATRIX_HEIGHT):
|
||||
for x in range(MATRIX_WIDTH):
|
||||
self.matrix[(y,x)] = None
|
||||
self.mqtt.subscribe("deckentetris/"+str(offset)+"/action", 2)
|
||||
self.mqtt.on_message = self.on_msg
|
||||
self.mqtt.loop_start()
|
||||
"""
|
||||
`self.matrix` is the current state of the tetris board, that is, it records which squares are
|
||||
currently occupied. It does not include the falling tetromino. The information relating to the
|
||||
@ -109,6 +109,15 @@ class Matris(object):
|
||||
self.linescleared_sound = get_sound("linecleared.wav")
|
||||
self.highscorebeaten_sound = get_sound("highscorebeaten.wav")
|
||||
|
||||
if ENABLE_MQTT:
|
||||
self.mqtt = mqtt.Client()
|
||||
self.mqtt.connect("mqtt.chaospott.de", port=1883, keepalive=60, bind_address="")
|
||||
self.mqtt.subscribe(MQTT_TOPIC+str(offset)+"/action", 2)
|
||||
self.mqtt.on_message = self.on_msg
|
||||
self.mqtt.loop_start()
|
||||
self.mqtt.publish(MQTT_TOPIC+str(offset)+"/current", payload=shape_str(self.current_tetromino.shape), qos=0, retain=False)
|
||||
self.mqtt.publish(MQTT_TOPIC+str(offset)+"/next", payload=shape_str(self.next_tetromino.shape), qos=0, retain=False)
|
||||
|
||||
|
||||
def set_tetrominoes(self):
|
||||
self.current_tetromino = self.next_tetromino
|
||||
@ -132,43 +141,45 @@ class Matris(object):
|
||||
def update(self, timepassed):
|
||||
self.needs_redraw = False
|
||||
|
||||
pressed = lambda key: event.type == pygame.KEYDOWN and event.key == key
|
||||
unpressed = lambda key: event.type == pygame.KEYUP and event.key == key
|
||||
#self.mqtt.loop()
|
||||
events = pygame.event.get()
|
||||
if ENABLE_KEYBOARD_CONTROLS:
|
||||
pressed = lambda key: event.type == pygame.KEYDOWN and event.key == key
|
||||
unpressed = lambda key: event.type == pygame.KEYUP and event.key == key
|
||||
|
||||
for event in events:
|
||||
if pressed(pygame.K_p):
|
||||
self.surface.fill((0,0,0))
|
||||
self.needs_redraw = True
|
||||
self.paused = not self.paused
|
||||
elif event.type == pygame.QUIT:
|
||||
self.gameover(full_exit=True)
|
||||
elif pressed(pygame.K_ESCAPE):
|
||||
self.gameover()
|
||||
events = pygame.event.get()
|
||||
|
||||
for event in events:
|
||||
if pressed(pygame.K_p):
|
||||
self.surface.fill((0,0,0))
|
||||
self.needs_redraw = True
|
||||
self.paused = not self.paused
|
||||
elif event.type == pygame.QUIT:
|
||||
self.gameover(full_exit=True)
|
||||
elif pressed(pygame.K_ESCAPE):
|
||||
self.gameover()
|
||||
|
||||
if self.paused:
|
||||
return self.needs_redraw
|
||||
|
||||
for event in events:
|
||||
if pressed(pygame.K_SPACE):
|
||||
self.hard_drop()
|
||||
elif pressed(pygame.K_UP) or pressed(pygame.K_w):
|
||||
self.request_rotation()
|
||||
if ENABLE_KEYBOARD_CONTROLS:
|
||||
for event in events:
|
||||
if pressed(pygame.K_SPACE):
|
||||
self.hard_drop()
|
||||
elif pressed(pygame.K_UP) or pressed(pygame.K_w):
|
||||
self.request_rotation()
|
||||
|
||||
elif pressed(pygame.K_LEFT) or pressed(pygame.K_a):
|
||||
self.request_movement('left')
|
||||
self.movement_keys['left'] = 1
|
||||
elif pressed(pygame.K_RIGHT) or pressed(pygame.K_d):
|
||||
self.request_movement('right')
|
||||
self.movement_keys['right'] = 1
|
||||
elif pressed(pygame.K_LEFT) or pressed(pygame.K_a):
|
||||
self.request_movement('left')
|
||||
self.movement_keys['left'] = 1
|
||||
elif pressed(pygame.K_RIGHT) or pressed(pygame.K_d):
|
||||
self.request_movement('right')
|
||||
self.movement_keys['right'] = 1
|
||||
|
||||
elif unpressed(pygame.K_LEFT) or unpressed(pygame.K_a):
|
||||
self.movement_keys['left'] = 0
|
||||
self.movement_keys_timer = (-self.movement_keys_speed)*2
|
||||
elif unpressed(pygame.K_RIGHT) or unpressed(pygame.K_d):
|
||||
self.movement_keys['right'] = 0
|
||||
self.movement_keys_timer = (-self.movement_keys_speed)*2
|
||||
elif unpressed(pygame.K_LEFT) or unpressed(pygame.K_a):
|
||||
self.movement_keys['left'] = 0
|
||||
self.movement_keys_timer = (-self.movement_keys_speed)*2
|
||||
elif unpressed(pygame.K_RIGHT) or unpressed(pygame.K_d):
|
||||
self.movement_keys['right'] = 0
|
||||
self.movement_keys_timer = (-self.movement_keys_speed)*2
|
||||
|
||||
|
||||
|
||||
@ -176,8 +187,12 @@ class Matris(object):
|
||||
self.downwards_speed = self.base_downwards_speed ** (1 + self.level/10.)
|
||||
|
||||
self.downwards_timer += timepassed
|
||||
downwards_speed = self.downwards_speed*0.10 if any([pygame.key.get_pressed()[pygame.K_DOWN],
|
||||
pygame.key.get_pressed()[pygame.K_s]]) else self.downwards_speed
|
||||
|
||||
if ENABLE_KEYBOARD_CONTROLS:
|
||||
downwards_speed = self.downwards_speed*0.10 if any([pygame.key.get_pressed()[pygame.K_DOWN],
|
||||
pygame.key.get_pressed()[pygame.K_s]]) else self.downwards_speed
|
||||
else:
|
||||
downwards_speed = self.downwards_speed
|
||||
if self.downwards_timer > downwards_speed:
|
||||
if not self.request_movement('down'):
|
||||
self.lock_tetromino()
|
||||
@ -185,11 +200,12 @@ class Matris(object):
|
||||
self.downwards_timer %= downwards_speed
|
||||
|
||||
|
||||
if any(self.movement_keys.values()):
|
||||
self.movement_keys_timer += timepassed
|
||||
if self.movement_keys_timer > self.movement_keys_speed:
|
||||
self.request_movement('right' if self.movement_keys['right'] else 'left')
|
||||
self.movement_keys_timer %= self.movement_keys_speed
|
||||
if ENABLE_KEYBOARD_CONTROLS:
|
||||
if any(self.movement_keys.values()):
|
||||
self.movement_keys_timer += timepassed
|
||||
if self.movement_keys_timer > self.movement_keys_speed:
|
||||
self.request_movement('right' if self.movement_keys['right'] else 'left')
|
||||
self.movement_keys_timer %= self.movement_keys_speed
|
||||
|
||||
return self.needs_redraw
|
||||
|
||||
@ -216,13 +232,15 @@ class Matris(object):
|
||||
is responsible for checking if it's game over.
|
||||
"""
|
||||
|
||||
write_score(self.score)
|
||||
|
||||
if full_exit:
|
||||
exit()
|
||||
else:
|
||||
raise GameOver("Sucker!")
|
||||
#write_score(self.score)
|
||||
|
||||
#if full_exit:
|
||||
# exit()
|
||||
#else:
|
||||
# raise GameOver("Sucker!")
|
||||
self.paused = True
|
||||
self.surface.fill(GAMEOVER_COLOR)
|
||||
self.needs_redraw =True
|
||||
def place_shadow(self):
|
||||
posY, posX = self.tetromino_position
|
||||
while self.blend(position=(posY, posX)):
|
||||
@ -333,17 +351,18 @@ class Matris(object):
|
||||
self.lines += lines_cleared
|
||||
|
||||
if lines_cleared:
|
||||
if lines_cleared >= 4:
|
||||
if lines_cleared >= 4 and ENABLE_SOUND:
|
||||
self.linescleared_sound.play()
|
||||
self.score += 100 * (lines_cleared**2) * self.combo
|
||||
|
||||
if not self.played_highscorebeaten_sound and self.score > self.highscore:
|
||||
if self.highscore != 0:
|
||||
if self.highscore != 0 and ENABLE_SOUND:
|
||||
self.highscorebeaten_sound.play()
|
||||
self.played_highscorebeaten_sound = True
|
||||
|
||||
if self.lines >= self.level*10:
|
||||
self.levelup_sound.play()
|
||||
if ENABLE_SOUND:
|
||||
self.levelup_sound.play()
|
||||
self.level += 1
|
||||
|
||||
self.combo = self.combo + 1 if lines_cleared else 1
|
||||
@ -351,7 +370,8 @@ class Matris(object):
|
||||
self.set_tetrominoes()
|
||||
|
||||
if not self.blend():
|
||||
self.gameover_sound.play()
|
||||
if ENABLE_SOUND:
|
||||
self.gameover_sound.play()
|
||||
self.gameover()
|
||||
|
||||
self.needs_redraw = True
|
||||
@ -450,8 +470,9 @@ class Game(object):
|
||||
|
||||
pygame.display.flip()
|
||||
if ENABLE_STDIO:
|
||||
#print(screen.get_view('2'))
|
||||
os.write(1, screen.get_view('2'))
|
||||
#print("-------------")
|
||||
#print(pygame.image.tostring(screen, "RGB", False))
|
||||
os.write(1, pygame.image.tostring(screen, "RGB", False))
|
||||
|
||||
|
||||
def blit_next_tetromino(self, tetromino_surf, offset):
|
||||
@ -498,9 +519,14 @@ def construct_nightmare(size):
|
||||
|
||||
if __name__ == '__main__':
|
||||
pygame.init()
|
||||
|
||||
print("Width:", WIDTH, "Height:", HEIGHT, "Playercount:", PLAYER)
|
||||
if ENABLE_MQTT or True:
|
||||
print("MQTT enabled:")
|
||||
print("TOPIC:", MQTT_TOPIC+"<playerid>/action", " PAYLOAD: left|right|rotate|drop|update")
|
||||
print("TOPIC:", MQTT_TOPIC+"<playerid>/current", "Show the current tetromino. Updated by update @ /action.")
|
||||
print("TOPIC:", MQTT_TOPIC+"<playerid>/next", "Show the current tetromino. Updated by update @ /action.")
|
||||
screen = pygame.display.set_mode((WIDTH, HEIGHT))
|
||||
pygame.display.set_caption("MaTris")
|
||||
pygame.display.set_caption("Deckentetris")
|
||||
# Menu().main(screen)
|
||||
Game().main(screen)
|
||||
|
||||
|
Reference in New Issue
Block a user