generated from mwc/project_game
Started retro tetris game
Started developing a retro version of Tetris, following the planning on the board of the classroom (see planning.jpg). Moved cursor work into cursor.
This commit is contained in:
10
block.py
Normal file
10
block.py
Normal file
@@ -0,0 +1,10 @@
|
||||
class Block:
|
||||
"""A Block represents a single square on the Tetris board.
|
||||
Blocks are part of a Piece while they are 'alive'.
|
||||
"""
|
||||
character = "X"
|
||||
color = "blue"
|
||||
alive = True
|
||||
|
||||
def __init__(self, position):
|
||||
self.position = position
|
||||
7
game.py
Normal file
7
game.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from retro.game import Game
|
||||
from manager import Manager
|
||||
|
||||
agents = [Manager()]
|
||||
state = {'level': 1}
|
||||
game = Game(agents, state, board_size=(20, 20), debug=True)
|
||||
game.play()
|
||||
24
manager.py
Normal file
24
manager.py
Normal file
@@ -0,0 +1,24 @@
|
||||
from piece import Piece, PIECE_DEFINITIONS
|
||||
from random import choice
|
||||
from retro.errors import AgentNotFoundByName
|
||||
|
||||
class Manager:
|
||||
"""The Manager takes care of stuff that isn't anyone else's responsibility:
|
||||
- Create a Piece whenever none exists.
|
||||
- Clear full rows of Blocks (and move other Blocks down).
|
||||
- End the game when the Blocks pile up all the way.
|
||||
"""
|
||||
display = False
|
||||
|
||||
def play_turn(self, game):
|
||||
try:
|
||||
game.get_agent_by_name("piece")
|
||||
except AgentNotFoundByName:
|
||||
self.create_piece(game)
|
||||
|
||||
def create_piece(self, game):
|
||||
width, height = game.board_size
|
||||
piece = Piece((width//2, 2), game, choice(PIECE_DEFINITIONS))
|
||||
game.add_agent(piece)
|
||||
|
||||
|
||||
100
piece.py
Normal file
100
piece.py
Normal file
@@ -0,0 +1,100 @@
|
||||
from block import Block
|
||||
|
||||
PIECE_DEFINITIONS = [
|
||||
[(-1, 0), (0, 0), (1, 0), (2, 0)],
|
||||
[(0, 0), (1, 0), (0, 1), (1, 1)],
|
||||
]
|
||||
|
||||
class Piece:
|
||||
"""A Piece is a group of blocks which are 'alive':
|
||||
They fall and the player can rotate or move them.
|
||||
A Piece is created with a position, the game, and a list of block_offsets,
|
||||
each of which represents the location of one of the Piece's
|
||||
Blocks relative to the Piece position.
|
||||
"""
|
||||
name = "piece"
|
||||
display = False
|
||||
|
||||
def __init__(self, position, game, block_offsets):
|
||||
self.position = position
|
||||
self.blocks = {}
|
||||
for offset in block_offsets:
|
||||
self.create_block(game, offset)
|
||||
|
||||
def handle_keystroke(self, keystroke, game):
|
||||
x, y = self.position
|
||||
if keystroke.name == "KEY_LEFT":
|
||||
new_position = (x - 1, y)
|
||||
if self.can_move_to(new_position, game):
|
||||
self.move_to(new_position)
|
||||
elif keystroke.name == "KEY_RIGHT":
|
||||
new_position = (x + 1, y)
|
||||
if self.can_move_to(new_position, game):
|
||||
self.move_to(new_position)
|
||||
|
||||
def play_turn(self, game):
|
||||
if self.should_fall(game):
|
||||
self.fall(game)
|
||||
|
||||
def should_fall(self, game):
|
||||
"""Determines whether the piece should fall.
|
||||
Currently, the Piece falls every third turn.
|
||||
In the future, the Piece should fall slowly at first, and
|
||||
then should fall faster at higher levels.
|
||||
"""
|
||||
return game.turn_number % 3 == 0
|
||||
|
||||
def fall(self, game):
|
||||
x, y = self.position
|
||||
falling_position = (x, y + 1)
|
||||
if self.can_move_to(falling_position, game):
|
||||
self.move_to(falling_position)
|
||||
else:
|
||||
self.destroy(game)
|
||||
|
||||
def can_move_to(self, new_position, game):
|
||||
"""Checks whether the Piece can move to a new position.
|
||||
For every one of the Piece's Blocks, finds where that block
|
||||
would be after the move, and checks whether there are any dead agents
|
||||
already there (live agents would be Blocks which are part of this Piece,
|
||||
not a problem since they'll be moving too).
|
||||
"""
|
||||
x, y = new_position
|
||||
agents_by_position = game.get_agents_by_position()
|
||||
for offset in self.blocks.keys():
|
||||
ox, oy = offset
|
||||
new_block_position = (x+ox, y+oy)
|
||||
if not game.on_board(new_block_position):
|
||||
return False
|
||||
for agent in agents_by_position[new_block_position]:
|
||||
if not agent.alive:
|
||||
return False
|
||||
return True
|
||||
|
||||
def move_to(self, position):
|
||||
"""Move to position and updates positions of Blocks.
|
||||
"""
|
||||
x, y = position
|
||||
self.position = position
|
||||
for offset, block in self.blocks.items():
|
||||
ox, oy = offset
|
||||
block.position = (x + ox, y + oy)
|
||||
|
||||
def create_block(self, game, offset):
|
||||
x, y = self.position
|
||||
ox, oy = offset
|
||||
block = Block((x + ox, y + oy))
|
||||
self.blocks[offset] = block
|
||||
game.add_agent(block)
|
||||
|
||||
def destroy(self, game):
|
||||
"""Causes the Piece to destroy itself.
|
||||
All the Blocks are set to dead.
|
||||
"""
|
||||
for block in self.blocks.values():
|
||||
block.alive = False
|
||||
game.remove_agent(self)
|
||||
|
||||
|
||||
|
||||
|
||||
BIN
planning.jpg
Normal file
BIN
planning.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.9 MiB |
8
poetry.lock
generated
8
poetry.lock
generated
@@ -1,4 +1,4 @@
|
||||
# This file is automatically @generated by Poetry 2.0.0 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "ansicon"
|
||||
@@ -48,14 +48,14 @@ ansicon = {version = "*", markers = "platform_system == \"Windows\""}
|
||||
|
||||
[[package]]
|
||||
name = "retro-games"
|
||||
version = "1.1.0"
|
||||
version = "1.1.3"
|
||||
description = "A simple framework for Terminal-based games"
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.10"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "retro_games-1.1.0-py3-none-any.whl", hash = "sha256:c621117e4dd528b1e4870d897d00c4365566ab3ba965177e3996ed3c889dd9f8"},
|
||||
{file = "retro_games-1.1.0.tar.gz", hash = "sha256:2167b574f42fe1e739b7c9ec75e98a9b76df42e2166376b85559291b3dc58f82"},
|
||||
{file = "retro_games-1.1.3-py3-none-any.whl", hash = "sha256:4bdd27241b5cb3ee72e69a042d301ff58df2a2ade7e3c29400a538fa54e30148"},
|
||||
{file = "retro_games-1.1.3.tar.gz", hash = "sha256:4f91ff725e551820aa4e30c12c0264e2da41967ed34252122b7136bc2a8ed311"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
||||
Reference in New Issue
Block a user