generated from mwc/project_game
da thang
This commit is contained in:
98
Snake/Bike.py
Normal file
98
Snake/Bike.py
Normal file
@@ -0,0 +1,98 @@
|
||||
"""
|
||||
|
||||
from trail import SnakeBodySegment
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class SnakeHead:
|
||||
"""An Agent representing the snake's head. When the game starts, you control
|
||||
the snake head using the arrow keys. The SnakeHead always has a direction, and
|
||||
will keep moving in that direction every turn. When you press an arrow key,
|
||||
you change the SnakeHead's direction.
|
||||
|
||||
Attributes:
|
||||
name: "Snake head"
|
||||
position: (0,0)
|
||||
character: ``'v'`` Depending on the snake head's direction, its character
|
||||
changes to ``'<'``, ``'^'``, ``'>'``, or ``'v'``.
|
||||
next_segment: Initially ``None``, this is a reference to a SnakeBodySegment.
|
||||
growing: When set to True, the snake will grow a new segment on its next move.
|
||||
"""
|
||||
RIGHT = (1, 0)
|
||||
UP = (0, -1)
|
||||
LEFT = (-1, 0)
|
||||
DOWN = (0, 1)
|
||||
name = "Snake head"
|
||||
position = (0, 0)
|
||||
direction = DOWN
|
||||
character = 'v'
|
||||
next_segment = None
|
||||
growing = False
|
||||
|
||||
def play_turn(self, game):
|
||||
"""On each turn, the snake head uses its position and direction to figure out
|
||||
its next position. If the snake head is able to move there (it's on the board and
|
||||
not occuppied by part of the snake's body), it moves.
|
||||
|
||||
Then, if the snake head is on the Apple, the Apple moves to a new random position
|
||||
and ``growing`` is set to True.
|
||||
|
||||
Now we need to deal with two situations. First, if ``next_segment`` is not None, there is
|
||||
a SnakeBodySegment attached to the head. We need the body to follow the head,
|
||||
so we call ``self.next_segment.move``, passing the head's old position
|
||||
(this will be the body's new position), a reference to the game, and a value for
|
||||
``growing``. If the snake needs to grow, we need to pass this information along
|
||||
the body until it reaches the tail--this is where the next segment will be attached.
|
||||
|
||||
If there is no ``next_segment`` but ``self.growing`` is True, it's time to add
|
||||
a body! We set ``self.next_segment`` to a new SnakeBodySegment, set its
|
||||
position to the head's old position, and add it to the game. We also add 1 to the
|
||||
game's score.
|
||||
"""
|
||||
x, y = self.position
|
||||
dx, dy = self.direction
|
||||
if self.can_move((x+dx, y+dy), game):
|
||||
self.position = (x+dx, y+dy)
|
||||
if self.is_on_apple(self.position, game):
|
||||
apple = game.get_agent_by_name("Apple")
|
||||
apple.relocate(game)
|
||||
self.growing = True
|
||||
if self.next_segment:
|
||||
self.next_segment.move((x, y), game, growing=self.growing)
|
||||
elif self.growing:
|
||||
self.next_segment = SnakeBodySegment(1, (x, y))
|
||||
game.add_agent(self.next_segment)
|
||||
game.state['score'] += 1
|
||||
self.growing = False
|
||||
|
||||
|
||||
def handle_keystroke(self, keystroke, game):
|
||||
"""Checks whether one of the arrow keys has been pressed.
|
||||
If so, sets the SnakeHead's direction and character.
|
||||
"""
|
||||
x, y = self.position
|
||||
if keystroke.name == "KEY_RIGHT":
|
||||
self.direction = self.RIGHT
|
||||
self.character = '>'
|
||||
elif keystroke.name == "KEY_UP":
|
||||
self.direction = self.UP
|
||||
self.character = '^'
|
||||
elif keystroke.name == "KEY_LEFT":
|
||||
self.direction = self.LEFT
|
||||
self.character = '<'
|
||||
elif keystroke.name == "KEY_DOWN":
|
||||
self.direction = self.DOWN
|
||||
self.character = 'v'
|
||||
|
||||
|
||||
def can_move(self, position, game):
|
||||
on_board = game.on_board(position)
|
||||
empty = game.is_empty(position)
|
||||
on_apple = self.is_on_apple(position, game)
|
||||
return on_board and (empty or on_apple)
|
||||
|
||||
def is_on_apple(self, position, game):
|
||||
apple = game.get_agent_by_name("Apple")
|
||||
return apple.position == position
|
||||
56
Snake/Trail.py
Normal file
56
Snake/Trail.py
Normal file
@@ -0,0 +1,56 @@
|
||||
"""
|
||||
|
||||
|
||||
|
||||
|
||||
class SnakeBodySegment:
|
||||
"""Finally, we need an Agent for the snake's body segments.
|
||||
SnakeBodySegment doesn't have ``play_turn`` or ``handle_keystroke`` methods because
|
||||
it never does anything on its own. It only moves when the SnakeHead, or the previous
|
||||
segment, tells it to move.
|
||||
|
||||
Arguments:
|
||||
segment_id (int): Keeps track of how far back this segment is from the head.
|
||||
This is used to give the segment a unique name, and also to keep track
|
||||
of how many points the player earns for eating the next apple.
|
||||
position (int, int): The initial position.
|
||||
|
||||
Attributes:
|
||||
character: '*'
|
||||
next_segment: Initially ``None``, this is a reference to a SnakeBodySegment
|
||||
when this segment is not the last one in the snake's body.
|
||||
|
||||
"""
|
||||
character = '*'
|
||||
next_segment = None
|
||||
|
||||
def __init__(self, segment_id, position):
|
||||
self.segment_id = segment_id
|
||||
self.name = f"Snake body segment {segment_id}"
|
||||
self.position = position
|
||||
|
||||
def move(self, new_position, game, growing=False):
|
||||
"""When SnakeHead moves, it sets off a chain reaction, moving all its
|
||||
body segments. Whenever the head or a body segment has another segment
|
||||
(``next_segment``), it calls that segment's ``move`` method.
|
||||
|
||||
This method updates the SnakeBodySegment's position. Then, if
|
||||
``self.next_segment`` is not None, calls that segment's ``move`` method.
|
||||
If there is no next segment and ``growing`` is True, then we set
|
||||
``self.next_segment`` to a new SnakeBodySegment in this segment's old
|
||||
position, and update the game's score.
|
||||
|
||||
Arguments:
|
||||
new_position (int, int): The new position.
|
||||
game (Game): A reference to the current game.
|
||||
growing (bool): (Default False) When True, the snake needs to
|
||||
add a new segment.
|
||||
"""
|
||||
old_position = self.position
|
||||
self.position = new_position
|
||||
if self.next_segment:
|
||||
self.next_segment.move(old_position, game, growing=growing)
|
||||
elif growing:
|
||||
self.next_segment = SnakeBodySegment(self.segment_id + 1, old_position)
|
||||
game.add_agent(self.next_segment)
|
||||
game.state['score'] += self.segment_id + 1
|
||||
BIN
Snake/__pycache__/bike.cpython-311.pyc
Normal file
BIN
Snake/__pycache__/bike.cpython-311.pyc
Normal file
Binary file not shown.
BIN
Snake/__pycache__/trail.cpython-311.pyc
Normal file
BIN
Snake/__pycache__/trail.cpython-311.pyc
Normal file
Binary file not shown.
67
Snake/nav_game.py
Normal file
67
Snake/nav_game.py
Normal file
@@ -0,0 +1,67 @@
|
||||
"""
|
||||
|
||||
|
||||
|
||||
from random import randint
|
||||
from retro.game import Game
|
||||
from bike import SnakeHead
|
||||
|
||||
|
||||
class Apple:
|
||||
"""An agent representing the Apple.
|
||||
Note how Apple doesn't have ``play_turn`` or
|
||||
``handle_keystroke`` methods: the Apple doesn't need to do
|
||||
anything in this game. It just sits there waiting to get
|
||||
eaten.
|
||||
|
||||
Attributes:
|
||||
name: "Apple"
|
||||
character: '@'
|
||||
color: "red_on_black" (`Here's documentation on how colors
|
||||
work <https://blessed.readthedocs.io/en/latest/colors.html>`_
|
||||
position: (0, 0). The Apple will choose a random position
|
||||
as soon as the game starts, but it needs an initial
|
||||
position to be assigned.
|
||||
|
||||
"""
|
||||
name = "Apple"
|
||||
character = '@'
|
||||
color = "red_on_black"
|
||||
position = (0, 0)
|
||||
|
||||
def relocate(self, game):
|
||||
"""Sets position to a random empty position. This method is
|
||||
called whenever the snake's head touches the apple.
|
||||
|
||||
Arguments:
|
||||
game (Game): The current game.
|
||||
"""
|
||||
self.position = self.random_empty_position(game)
|
||||
|
||||
|
||||
def random_empty_position(self, game):
|
||||
"""Returns a randomly-selected empty position. Uses a very
|
||||
simple algorithm: Get the game's board size, choose a
|
||||
random x-value between 0 and the board width, and choose
|
||||
a random y-value between 0 and the board height. Now use
|
||||
the game to check whether any Agents are occupying this
|
||||
position. If so, keep randomly choosing a new position
|
||||
until the position is empty.
|
||||
"""
|
||||
bw, bh = game.board_size
|
||||
occupied_positions = game.get_agents_by_position()
|
||||
while True:
|
||||
position = (randint(0, bw-1), randint(0, bh-1))
|
||||
if position not in occupied_positions:
|
||||
return position
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
head = SnakeHead()
|
||||
apple = Apple()
|
||||
game = Game([head, apple], {'score': 0}, board_size=(32, 16), framerate=12)
|
||||
apple.relocate(game)
|
||||
game.play()
|
||||
144
Tron/Bike.py
Normal file
144
Tron/Bike.py
Normal file
@@ -0,0 +1,144 @@
|
||||
from Trail import TrailSegment
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class Bike:
|
||||
|
||||
|
||||
|
||||
"""An Agent representing the snake's head. When the game starts, you control
|
||||
the snake head using the arrow keys. The Bike always has a direction, and
|
||||
will keep moving in that direction every turn. When you press an arrow key,
|
||||
you change the Bike's direction.
|
||||
|
||||
Attributes:
|
||||
name: "Snake head"
|
||||
position: (0,0)
|
||||
character: ``'v'`` Depending on the snake head's direction, its character
|
||||
changes to ``'<'``, ``'^'``, ``'>'``, or ``'v'``.
|
||||
next_segment: Initially ``None``, this is a reference to a SnakeBodySegment.
|
||||
growing: When set to True, the snake will grow a new segment on its next move.
|
||||
"""
|
||||
RIGHT = (1, 0)
|
||||
UP = (0, -1)
|
||||
LEFT = (-1, 0)
|
||||
DOWN = (0, 1)
|
||||
next_segment = None
|
||||
growing = False
|
||||
turn_counter = 0
|
||||
GROW_INTERVAL = 5 # The bike will grow 1 segment longer every 5 turns.
|
||||
|
||||
|
||||
|
||||
|
||||
def __init__(self, player_number, start_position, start_direction):
|
||||
self.player_number = player_number
|
||||
self.position = start_position
|
||||
self.direction = start_direction
|
||||
self.name = f"Bike {player_number}"
|
||||
if self.player_number == 1:
|
||||
self.color = "bright_blue"
|
||||
else:
|
||||
self.color = "bright_red"
|
||||
|
||||
# Adjust starting character based on starting direction
|
||||
if start_direction == self.RIGHT: self.character = '>'
|
||||
elif start_direction == self.LEFT: self.character = '<'
|
||||
elif start_direction == self.UP: self.character = '^'
|
||||
elif start_direction == self.DOWN: self.character = 'v'
|
||||
|
||||
|
||||
def play_turn(self, game):
|
||||
"""On each turn, the snake head uses its position and direction to figure out
|
||||
its next position. If the snake head is able to move there (it's on the board and
|
||||
not occuppied by part of the snake's body), it moves.
|
||||
|
||||
Then, if the snake head is on the Apple, the Apple moves to a new random position
|
||||
and ``growing`` is set to True.
|
||||
|
||||
Now we need to deal with two situations. First, if ``next_segment`` is not None, there is
|
||||
a SnakeBodySegment attached to the head. We need the body to follow the head,
|
||||
so we call ``self.next_segment.move``, passing the head's old position
|
||||
(this will be the body's new position), a reference to the game, and a value for
|
||||
``growing``. If the snake needs to grow, we need to pass this information along
|
||||
the body until it reaches the tail--this is where the next segment will be attached.
|
||||
|
||||
If there is no ``next_segment`` but ``self.growing`` is True, it's time to add
|
||||
a body! We set ``self.next_segment`` to a new SnakeBodySegment, set its
|
||||
position to the head's old position, and add it to the game. We also add 1 to the
|
||||
game's score.
|
||||
"""
|
||||
# 1. Increment turn counter and check if it's time to grow
|
||||
self.turn_counter += 1
|
||||
if self.turn_counter >= self.GROW_INTERVAL:
|
||||
self.growing = True
|
||||
self.turn_counter = 0 # Reset the counter for the next growth cycle
|
||||
|
||||
|
||||
x, y = self.position
|
||||
dx, dy = self.direction
|
||||
if self.can_move((x+dx, y+dy), game):
|
||||
self.position = (x+dx, y+dy)
|
||||
if self.next_segment:
|
||||
self.next_segment.move((x, y), game, growing=self.growing)
|
||||
elif self.growing:
|
||||
self.next_segment = TrailSegment(1, (x, y), self.player_number)
|
||||
game.add_agent(self.next_segment)
|
||||
self.growing = False
|
||||
else:
|
||||
game.end()
|
||||
print(f"Player {self.player_number} died")
|
||||
|
||||
|
||||
def handle_keystroke(self, keystroke, game):
|
||||
"""Checks whether one of the arrow keys has been pressed.
|
||||
If so, sets the Bike's direction and character.
|
||||
"""
|
||||
|
||||
|
||||
x, y = self.position
|
||||
# --- PLAYER 1 CONTROLS (Arrow Keys) ---
|
||||
if self.player_number == 1:
|
||||
if keystroke.name == "KEY_RIGHT" and self.direction != self.LEFT:
|
||||
self.direction = self.RIGHT
|
||||
self.character = '>'
|
||||
elif keystroke.name == "KEY_UP" and self.direction != self.DOWN:
|
||||
self.direction = self.UP
|
||||
self.character = '^'
|
||||
elif keystroke.name == "KEY_LEFT" and self.direction != self.RIGHT:
|
||||
self.direction = self.LEFT
|
||||
self.character = '<'
|
||||
elif keystroke.name == "KEY_DOWN" and self.direction != self.UP:
|
||||
self.direction = self.DOWN
|
||||
self.character = 'v'
|
||||
|
||||
# --- PLAYER 2 CONTROLS (WASD Keys) ---
|
||||
elif self.player_number == 2:
|
||||
|
||||
key_name = str(keystroke)
|
||||
|
||||
if keystroke == "d" and self.direction != self.LEFT:
|
||||
self.direction = self.RIGHT
|
||||
self.character = '>'
|
||||
elif keystroke == "w" and self.direction != self.DOWN:
|
||||
self.direction = self.UP
|
||||
self.character = '^'
|
||||
elif keystroke == "a" and self.direction != self.RIGHT:
|
||||
self.direction = self.LEFT
|
||||
self.character = '<'
|
||||
elif keystroke == "s" and self.direction != self.UP:
|
||||
self.direction = self.DOWN
|
||||
self.character = 'v'
|
||||
|
||||
|
||||
def can_move(self, position, game):
|
||||
on_board = game.on_board(position)
|
||||
empty = game.is_empty(position)
|
||||
return on_board and empty
|
||||
'''
|
||||
def is_on_apple(self, position, game):
|
||||
apple = game.get_agent_by_name("Apple")
|
||||
return apple.position == position
|
||||
'''
|
||||
62
Tron/Trail.py
Normal file
62
Tron/Trail.py
Normal file
@@ -0,0 +1,62 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class TrailSegment:
|
||||
"""Finally, we need an Agent for the snake's body segments.
|
||||
SnakeBodySegment doesn't have ``play_turn`` or ``handle_keystroke`` methods because
|
||||
it never does anything on its own. It only moves when the Bike, or the previous
|
||||
segment, tells it to move.
|
||||
|
||||
Arguments:
|
||||
segment_id (int): Keeps track of how far back this segment is from the head.
|
||||
This is used to give the segment a unique name, and also to keep track
|
||||
of how many points the player earns for eating the next apple.
|
||||
position (int, int): The initial position.
|
||||
|
||||
Attributes:
|
||||
character: '*'
|
||||
next_segment: Initially ``None``, this is a reference to a TrailSegment
|
||||
when this segment is not the last one in the snake's Trail.
|
||||
|
||||
"""
|
||||
character = '*'
|
||||
next_segment = None
|
||||
|
||||
def __init__(self, segment_id, position, player_number): # Added player_number
|
||||
self.segment_id = segment_id
|
||||
self.player_number = player_number
|
||||
# Give it a completely unique name per player
|
||||
self.name = f"P{player_number} Trail segment {segment_id}"
|
||||
self.position = position
|
||||
if self.player_number == 1:
|
||||
self.color = "bright_blue"
|
||||
else:
|
||||
self.color = "bright_red"
|
||||
|
||||
def move(self, new_position, game, growing=False):
|
||||
"""When Bike moves, it sets off a chain reaction, moving all its
|
||||
Trail segments. Whenever the head or a Trail segment has another segment
|
||||
(``next_segment``), it calls that segment's ``move`` method.
|
||||
|
||||
This method updates the TrailSegment's position. Then, if
|
||||
``self.next_segment`` is not None, calls that segment's ``move`` method.
|
||||
If there is no next segment and ``growing`` is True, then we set
|
||||
``self.next_segment`` to a new SnakeBodySegment in this segment's old
|
||||
position, and update the game's score.
|
||||
|
||||
Arguments:
|
||||
new_position (int, int): The new position.
|
||||
game (Game): A reference to the current game.
|
||||
growing (bool): (Default False) When True, the snake needs to
|
||||
add a new segment.
|
||||
"""
|
||||
old_position = self.position
|
||||
self.position = new_position
|
||||
if self.next_segment:
|
||||
self.next_segment.move(old_position, game, growing=growing)
|
||||
elif growing:
|
||||
self.next_segment = TrailSegment(self.segment_id + 1, old_position, self.player_number)
|
||||
game.add_agent(self.next_segment)
|
||||
|
||||
BIN
Tron/__pycache__/Bike.cpython-311.pyc
Normal file
BIN
Tron/__pycache__/Bike.cpython-311.pyc
Normal file
Binary file not shown.
BIN
Tron/__pycache__/Trail.cpython-311.pyc
Normal file
BIN
Tron/__pycache__/Trail.cpython-311.pyc
Normal file
Binary file not shown.
BIN
Tron/__pycache__/bike.cpython-311.pyc
Normal file
BIN
Tron/__pycache__/bike.cpython-311.pyc
Normal file
Binary file not shown.
BIN
Tron/__pycache__/trail.cpython-311.pyc
Normal file
BIN
Tron/__pycache__/trail.cpython-311.pyc
Normal file
Binary file not shown.
18
Tron/nav_game.py
Normal file
18
Tron/nav_game.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# cd ~/Desktop/making_with_code/mwc1/unit3/project_game/Tron
|
||||
# python nav_game.py
|
||||
|
||||
|
||||
from random import randint
|
||||
from retro.game import Game
|
||||
from Bike import Bike
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Initialize Player 1: Player #1, starting at position (5, 8), moving RIGHT
|
||||
p1 = Bike(player_number=1, start_position=(5, 8), start_direction=Bike.RIGHT)
|
||||
|
||||
# Initialize Player 2: Player #2, starting at position (25, 8), moving LEFT
|
||||
p2 = Bike(player_number=2, start_position=(25, 8), start_direction=Bike.LEFT)
|
||||
|
||||
# Create and start the game with both bikes
|
||||
game = Game([p1, p2], {"*": "Play on!"}, board_size=(32, 16), framerate=8)
|
||||
game.play()
|
||||
143
Tron_arcade/Bike.py
Normal file
143
Tron_arcade/Bike.py
Normal file
@@ -0,0 +1,143 @@
|
||||
from Trail import TrailSegment
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class Bike:
|
||||
|
||||
|
||||
|
||||
"""An Agent representing the snake's head. When the game starts, you control
|
||||
the snake head using the arrow keys. The Bike always has a direction, and
|
||||
will keep moving in that direction every turn. When you press an arrow key,
|
||||
you change the Bike's direction.
|
||||
|
||||
Attributes:
|
||||
name: "Snake head"
|
||||
position: (0,0)
|
||||
character: ``'v'`` Depending on the snake head's direction, its character
|
||||
changes to ``'<'``, ``'^'``, ``'>'``, or ``'v'``.
|
||||
next_segment: Initially ``None``, this is a reference to a SnakeBodySegment.
|
||||
growing: When set to True, the snake will grow a new segment on its next move.
|
||||
"""
|
||||
RIGHT = (1, 0)
|
||||
UP = (0, -1)
|
||||
LEFT = (-1, 0)
|
||||
DOWN = (0, 1)
|
||||
next_segment = None
|
||||
growing = False
|
||||
turn_counter = 0
|
||||
GROW_INTERVAL = 5 # The bike will grow 1 segment longer every 5 turns.
|
||||
|
||||
|
||||
|
||||
|
||||
def __init__(self, player_number, start_position, start_direction):
|
||||
self.player_number = player_number
|
||||
self.position = start_position
|
||||
self.direction = start_direction
|
||||
self.name = f"Bike {player_number}"
|
||||
if self.player_number == 1:
|
||||
self.color = "bright_blue"
|
||||
else:
|
||||
self.color = "bright_red"
|
||||
|
||||
# Adjust starting character based on starting direction
|
||||
if start_direction == self.RIGHT: self.character = '>'
|
||||
elif start_direction == self.LEFT: self.character = '<'
|
||||
elif start_direction == self.UP: self.character = '^'
|
||||
elif start_direction == self.DOWN: self.character = 'v'
|
||||
|
||||
|
||||
def play_turn(self, game):
|
||||
"""On each turn, the snake head uses its position and direction to figure out
|
||||
its next position. If the snake head is able to move there (it's on the board and
|
||||
not occuppied by part of the snake's body), it moves.
|
||||
|
||||
Then, if the snake head is on the Apple, the Apple moves to a new random position
|
||||
and ``growing`` is set to True.
|
||||
|
||||
Now we need to deal with two situations. First, if ``next_segment`` is not None, there is
|
||||
a SnakeBodySegment attached to the head. We need the body to follow the head,
|
||||
so we call ``self.next_segment.move``, passing the head's old position
|
||||
(this will be the body's new position), a reference to the game, and a value for
|
||||
``growing``. If the snake needs to grow, we need to pass this information along
|
||||
the body until it reaches the tail--this is where the next segment will be attached.
|
||||
|
||||
If there is no ``next_segment`` but ``self.growing`` is True, it's time to add
|
||||
a body! We set ``self.next_segment`` to a new SnakeBodySegment, set its
|
||||
position to the head's old position, and add it to the game. We also add 1 to the
|
||||
game's score.
|
||||
"""
|
||||
# 1. Increment turn counter and check if it's time to grow
|
||||
self.turn_counter += 1
|
||||
if self.turn_counter >= self.GROW_INTERVAL:
|
||||
self.growing = True
|
||||
self.turn_counter = 0 # Reset the counter for the next growth cycle
|
||||
|
||||
|
||||
x, y = self.position
|
||||
dx, dy = self.direction
|
||||
if self.can_move((x+dx, y+dy), game):
|
||||
self.position = (x+dx, y+dy)
|
||||
if self.next_segment:
|
||||
self.next_segment.move((x, y), game, growing=self.growing)
|
||||
elif self.growing:
|
||||
self.next_segment = TrailSegment(1, (x, y), self.player_number)
|
||||
game.add_agent(self.next_segment)
|
||||
self.growing = False
|
||||
else:
|
||||
game.end()
|
||||
|
||||
|
||||
def handle_keystroke(self, keystroke, game):
|
||||
"""Checks whether one of the arrow keys has been pressed.
|
||||
If so, sets the Bike's direction and character.
|
||||
"""
|
||||
|
||||
|
||||
x, y = self.position
|
||||
# --- PLAYER 1 CONTROLS (Arrow Keys) ---
|
||||
if self.player_number == 1:
|
||||
if keystroke.name == "d" and self.direction != self.LEFT:
|
||||
self.direction = self.RIGHT
|
||||
self.character = '>'
|
||||
elif keystroke.name == "w" and self.direction != self.DOWN:
|
||||
self.direction = self.UP
|
||||
self.character = '^'
|
||||
elif keystroke.name == "a" and self.direction != self.RIGHT:
|
||||
self.direction = self.LEFT
|
||||
self.character = '<'
|
||||
elif keystroke.name == "s" and self.direction != self.UP:
|
||||
self.direction = self.DOWN
|
||||
self.character = 'v'
|
||||
|
||||
# --- PLAYER 2 CONTROLS (WASD Keys) ---
|
||||
elif self.player_number == 2:
|
||||
|
||||
key_name = str(keystroke)
|
||||
|
||||
if keystroke == "6" and self.direction != self.LEFT:
|
||||
self.direction = self.RIGHT
|
||||
self.character = '>'
|
||||
elif keystroke == "8" and self.direction != self.DOWN:
|
||||
self.direction = self.UP
|
||||
self.character = '^'
|
||||
elif keystroke == "4" and self.direction != self.RIGHT:
|
||||
self.direction = self.LEFT
|
||||
self.character = '<'
|
||||
elif keystroke == "2" and self.direction != self.UP:
|
||||
self.direction = self.DOWN
|
||||
self.character = 'v'
|
||||
|
||||
|
||||
def can_move(self, position, game):
|
||||
on_board = game.on_board(position)
|
||||
empty = game.is_empty(position)
|
||||
return on_board and empty
|
||||
'''
|
||||
def is_on_apple(self, position, game):
|
||||
apple = game.get_agent_by_name("Apple")
|
||||
return apple.position == position
|
||||
'''
|
||||
62
Tron_arcade/Trail.py
Normal file
62
Tron_arcade/Trail.py
Normal file
@@ -0,0 +1,62 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class TrailSegment:
|
||||
"""Finally, we need an Agent for the snake's body segments.
|
||||
SnakeBodySegment doesn't have ``play_turn`` or ``handle_keystroke`` methods because
|
||||
it never does anything on its own. It only moves when the Bike, or the previous
|
||||
segment, tells it to move.
|
||||
|
||||
Arguments:
|
||||
segment_id (int): Keeps track of how far back this segment is from the head.
|
||||
This is used to give the segment a unique name, and also to keep track
|
||||
of how many points the player earns for eating the next apple.
|
||||
position (int, int): The initial position.
|
||||
|
||||
Attributes:
|
||||
character: '*'
|
||||
next_segment: Initially ``None``, this is a reference to a TrailSegment
|
||||
when this segment is not the last one in the snake's Trail.
|
||||
|
||||
"""
|
||||
character = '*'
|
||||
next_segment = None
|
||||
|
||||
def __init__(self, segment_id, position, player_number): # Added player_number
|
||||
self.segment_id = segment_id
|
||||
self.player_number = player_number
|
||||
# Give it a completely unique name per player
|
||||
self.name = f"P{player_number} Trail segment {segment_id}"
|
||||
self.position = position
|
||||
if self.player_number == 1:
|
||||
self.color = "bright_blue"
|
||||
else:
|
||||
self.color = "bright_red"
|
||||
|
||||
def move(self, new_position, game, growing=False):
|
||||
"""When Bike moves, it sets off a chain reaction, moving all its
|
||||
Trail segments. Whenever the head or a Trail segment has another segment
|
||||
(``next_segment``), it calls that segment's ``move`` method.
|
||||
|
||||
This method updates the TrailSegment's position. Then, if
|
||||
``self.next_segment`` is not None, calls that segment's ``move`` method.
|
||||
If there is no next segment and ``growing`` is True, then we set
|
||||
``self.next_segment`` to a new SnakeBodySegment in this segment's old
|
||||
position, and update the game's score.
|
||||
|
||||
Arguments:
|
||||
new_position (int, int): The new position.
|
||||
game (Game): A reference to the current game.
|
||||
growing (bool): (Default False) When True, the snake needs to
|
||||
add a new segment.
|
||||
"""
|
||||
old_position = self.position
|
||||
self.position = new_position
|
||||
if self.next_segment:
|
||||
self.next_segment.move(old_position, game, growing=growing)
|
||||
elif growing:
|
||||
self.next_segment = TrailSegment(self.segment_id + 1, old_position, self.player_number)
|
||||
game.add_agent(self.next_segment)
|
||||
|
||||
BIN
Tron_arcade/__pycache__/Bike.cpython-311.pyc
Normal file
BIN
Tron_arcade/__pycache__/Bike.cpython-311.pyc
Normal file
Binary file not shown.
BIN
Tron_arcade/__pycache__/Trail.cpython-311.pyc
Normal file
BIN
Tron_arcade/__pycache__/Trail.cpython-311.pyc
Normal file
Binary file not shown.
BIN
Tron_arcade/__pycache__/bike.cpython-311.pyc
Normal file
BIN
Tron_arcade/__pycache__/bike.cpython-311.pyc
Normal file
Binary file not shown.
BIN
Tron_arcade/__pycache__/trail.cpython-311.pyc
Normal file
BIN
Tron_arcade/__pycache__/trail.cpython-311.pyc
Normal file
Binary file not shown.
18
Tron_arcade/nav_game.py
Normal file
18
Tron_arcade/nav_game.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# cd ~/Desktop/making_with_code/mwc1/unit3/project_game/Tron
|
||||
# python nav_game.py
|
||||
|
||||
|
||||
from random import randint
|
||||
from retro.game import Game
|
||||
from Bike import Bike
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Initialize Player 1: Player #1, starting at position (5, 8), moving RIGHT
|
||||
p1 = Bike(player_number=1, start_position=(5, 8), start_direction=Bike.RIGHT)
|
||||
|
||||
# Initialize Player 2: Player #2, starting at position (25, 8), moving LEFT
|
||||
p2 = Bike(player_number=2, start_position=(25, 8), start_direction=Bike.LEFT)
|
||||
|
||||
# Create and start the game with both bikes
|
||||
game = Game([p1, p2], {"*": "Play on!"}, board_size=(32, 16), framerate=8)
|
||||
game.play()
|
||||
81
poetry.lock
generated
Normal file
81
poetry.lock
generated
Normal file
@@ -0,0 +1,81 @@
|
||||
# This file is automatically @generated by Poetry 2.3.1 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "ansicon"
|
||||
version = "1.89.0"
|
||||
description = "Python wrapper for loading Jason Hood's ANSICON"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
groups = ["main"]
|
||||
markers = "platform_system == \"Windows\""
|
||||
files = [
|
||||
{file = "ansicon-1.89.0-py2.py3-none-any.whl", hash = "sha256:f1def52d17f65c2c9682cf8370c03f541f410c1752d6a14029f97318e4b9dfec"},
|
||||
{file = "ansicon-1.89.0.tar.gz", hash = "sha256:e4d039def5768a47e4afec8e89e83ec3ae5a26bf00ad851f914d1240b444d2b1"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blessed"
|
||||
version = "1.28.0"
|
||||
description = "Easy, practical library for making terminal apps, by providing an elegant, well-documented interface to Colors, Keyboard input, and screen Positioning capabilities."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "blessed-1.28.0-py3-none-any.whl", hash = "sha256:51e386b8ec85a0ce2177ffd7269d0121218c380d793196d87333cba97271a79f"},
|
||||
{file = "blessed-1.28.0.tar.gz", hash = "sha256:91620abe30549a32720fb0d2359100247cb279f84c4974becd789aac4818695c"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
jinxed = {version = ">=1.1.0", markers = "platform_system == \"Windows\""}
|
||||
wcwidth = ">=0.5"
|
||||
|
||||
[package.extras]
|
||||
docs = ["Pillow", "Sphinx (>3)", "sphinx-paramlinks", "sphinx_rtd_theme", "sphinxcontrib-manpage"]
|
||||
|
||||
[[package]]
|
||||
name = "jinxed"
|
||||
version = "1.3.0"
|
||||
description = "Jinxed Terminal Library"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
groups = ["main"]
|
||||
markers = "platform_system == \"Windows\""
|
||||
files = [
|
||||
{file = "jinxed-1.3.0-py2.py3-none-any.whl", hash = "sha256:b993189f39dc2d7504d802152671535b06d380b26d78070559551cbf92df4fc5"},
|
||||
{file = "jinxed-1.3.0.tar.gz", hash = "sha256:1593124b18a41b7a3da3b078471442e51dbad3d77b4d4f2b0c26ab6f7d660dbf"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
ansicon = {version = "*", markers = "platform_system == \"Windows\""}
|
||||
|
||||
[[package]]
|
||||
name = "retro-games"
|
||||
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.3-py3-none-any.whl", hash = "sha256:4bdd27241b5cb3ee72e69a042d301ff58df2a2ade7e3c29400a538fa54e30148"},
|
||||
{file = "retro_games-1.1.3.tar.gz", hash = "sha256:4f91ff725e551820aa4e30c12c0264e2da41967ed34252122b7136bc2a8ed311"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
blessed = ">=1.20.0,<2.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "wcwidth"
|
||||
version = "0.5.0"
|
||||
description = "Measures the displayed width of unicode strings in a terminal"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "wcwidth-0.5.0-py3-none-any.whl", hash = "sha256:1efe1361b83b0ff7877b81ba57c8562c99cf812158b778988ce17ec061095695"},
|
||||
{file = "wcwidth-0.5.0.tar.gz", hash = "sha256:f89c103c949a693bf563377b2153082bf58e309919dfb7f27b04d862a0089333"},
|
||||
]
|
||||
|
||||
[metadata]
|
||||
lock-version = "2.1"
|
||||
python-versions = ">=3.10,<4.0"
|
||||
content-hash = "03cc38c17964eb2c920ecf014cbfcf966c0c719418a127947b33382f086a0a6e"
|
||||
@@ -1,8 +1,8 @@
|
||||
[project]
|
||||
name = "project-game"
|
||||
version = "5.0.0"
|
||||
description = ""
|
||||
authors = [{ name = "Chris Proctor", email = "chris@chrisproctor.net" }]
|
||||
[Tron]
|
||||
name = "Tron"
|
||||
version = "1.0.0"
|
||||
description = "This is like a V.S. snake game. Needs two players. P1 is blue and P2 is red."
|
||||
authors = [{ name = "Benjamin Potocki", email = "wpotocki@lockportschools.net" }]
|
||||
requires-python = ">=3.10,<4.0"
|
||||
readme = "README.md"
|
||||
license = { text = "MIT" }
|
||||
|
||||
Reference in New Issue
Block a user