From 8a75d7dc2ef754e3455ae53fe9f904f38173ad6f Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 7 May 2021 01:37:44 -0500 Subject: [PATCH 01/18] added game board and stats file --- game/common/enums.py | 1 + game/common/game_board.py | 54 +++++++++++++++++++++++++++++++++++++++ game/common/stats.py | 5 ++++ 3 files changed, 60 insertions(+) create mode 100644 game/common/game_board.py create mode 100644 game/common/stats.py diff --git a/game/common/enums.py b/game/common/enums.py index 4af2f58e..4e048794 100644 --- a/game/common/enums.py +++ b/game/common/enums.py @@ -9,3 +9,4 @@ class ObjectType: none = 0 action = 1 player = 2 + game_board = 3 diff --git a/game/common/game_board.py b/game/common/game_board.py new file mode 100644 index 00000000..78fa741f --- /dev/null +++ b/game/common/game_board.py @@ -0,0 +1,54 @@ +from game.common.game_object import GameObject +from game.common.enums import ObjectType, Classtype +from game.common.stats import GameStats +import math + + +class GameBoard(GameObject): + def __init__(self): + super().__init__() + self.object_type = ObjectType.game_board + + # pull width and height values from GameStats + self.width = GameStats.game_board_width + self.height = GameStats.game_board_height + + # instantiate lists with an empty list + self.player_list = [] + self.wall_list = [] + self.items_list = [] + self.upgrades_list = [] + + # this calculates starting radius to totally encompass the map at start + self.circle_radius = math.sqrt( ( self.width / 2 ) ** 2 + ( self.height / 2 ) ** 2 ) + + # set turn counter to 0, not sure the use for this yet + self.turn = 0 + + def to_json(self): + data = super().to_json() + + data['width'] = self.width + data['height'] = self.height + data['player_list'] = self.player_list + data['wall_list'] = self.wall_list + data['items_list'] = self.items_list + data['upgrades_list'] = self.upgrades_list + data['circle_radius'] = self.circle_radius + data['turn'] = self.turn + + return data + + def from_json(self, data): + super().from_json(data) + + self.width = data['width'] + self.height = data['height'] + + self.player_list = data['player_list'] + self.wall_list = data['wall_list'] + self.items_list = data['items_list'] + self.upgrades_list = data['upgrades_list'] + + self.circle_radius = data['circle_radius'] + self.turn = data['turn'] \ No newline at end of file diff --git a/game/common/stats.py b/game/common/stats.py new file mode 100644 index 00000000..0080d35f --- /dev/null +++ b/game/common/stats.py @@ -0,0 +1,5 @@ + + +class GameStats: + game_board_width = 500 + game_board_height = 500 \ No newline at end of file From 7fefa00fea9619cd9ecac4c77662da739b89b576 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 7 May 2021 02:11:14 -0500 Subject: [PATCH 02/18] fixed imports --- game/common/game_board.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/game/common/game_board.py b/game/common/game_board.py index 78fa741f..2a2b5ca0 100644 --- a/game/common/game_board.py +++ b/game/common/game_board.py @@ -1,5 +1,5 @@ from game.common.game_object import GameObject -from game.common.enums import ObjectType, Classtype +from game.common.enums import ObjectType from game.common.stats import GameStats import math From 9f446d69c2fc0306bc99545b535c0405d9812996 Mon Sep 17 00:00:00 2001 From: erickbickler Date: Thu, 20 May 2021 20:45:30 -0500 Subject: [PATCH 03/18] added obfuscate method --- game/common/game_board.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/game/common/game_board.py b/game/common/game_board.py index 2a2b5ca0..53d62b91 100644 --- a/game/common/game_board.py +++ b/game/common/game_board.py @@ -25,6 +25,11 @@ def __init__(self): # set turn counter to 0, not sure the use for this yet self.turn = 0 + def obfuscate(self): + super().obfuscate() + + self.player_list = None + def to_json(self): data = super().to_json() From 4a1df1993c984e660dab8514cd02f1994d3f6065 Mon Sep 17 00:00:00 2001 From: erickbickler Date: Thu, 20 May 2021 20:47:09 -0500 Subject: [PATCH 04/18] added lethal list --- game/common/game_board.py | 1 + 1 file changed, 1 insertion(+) diff --git a/game/common/game_board.py b/game/common/game_board.py index 53d62b91..b46dd793 100644 --- a/game/common/game_board.py +++ b/game/common/game_board.py @@ -18,6 +18,7 @@ def __init__(self): self.wall_list = [] self.items_list = [] self.upgrades_list = [] + self.lethal_list = [] # this calculates starting radius to totally encompass the map at start self.circle_radius = math.sqrt( ( self.width / 2 ) ** 2 + ( self.height / 2 ) ** 2 ) From acb02274e9d6d9124702b931f69655300c853f68 Mon Sep 17 00:00:00 2001 From: erickbickler Date: Thu, 20 May 2021 21:23:31 -0500 Subject: [PATCH 05/18] added unit tests --- game/common/game_board.py | 7 ++++--- game/test_suite/tests/test_game_board.py | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 game/test_suite/tests/test_game_board.py diff --git a/game/common/game_board.py b/game/common/game_board.py index b46dd793..32a85e13 100644 --- a/game/common/game_board.py +++ b/game/common/game_board.py @@ -5,13 +5,14 @@ class GameBoard(GameObject): - def __init__(self): + # the width and height parameters have default values to allow them to be set for unit testing purposes + def __init__(self, width=GameStats.game_board_width, height=GameStats.game_board_height): super().__init__() self.object_type = ObjectType.game_board # pull width and height values from GameStats - self.width = GameStats.game_board_width - self.height = GameStats.game_board_height + self.width = width + self.height = height # instantiate lists with an empty list self.player_list = [] diff --git a/game/test_suite/tests/test_game_board.py b/game/test_suite/tests/test_game_board.py new file mode 100644 index 00000000..df4dd504 --- /dev/null +++ b/game/test_suite/tests/test_game_board.py @@ -0,0 +1,21 @@ +import unittest +import math +from game.common.game_board import GameBoard + +class TestGameBoard(unittest.TestCase): + + def test_circle_radius(self): + # square board test + game_board1 = GameBoard(10, 10) + self.assertGreaterEqual(game_board1.circle_radius, math.sqrt(200)) # should succeed + self.assertAlmostEqual(game_board1.circle_radius, math.sqrt(200)) # if the first test fails, but this one succeeds, then there might be rounding errors + + # rectangular board test, width greater than height + game_board2 = GameBoard(15, 10) + self.assertGreaterEqual(game_board1.circle_radius, math.sqrt(325)) # should succeed + self.assertAlmostEqual(game_board1.circle_radius, math.sqrt(325)) # shows possible rounding errors + + # rectangular board test, height greater than width + game_board3 = GameBoard(10, 15) + self.assertGreaterEqual(game_board3.circle_radius, math.sqrt(325)) # should succeed + self.assertAlmostEqual(game_board3.circle_radius, math.sqrt(325)) # shows possible rounding errors \ No newline at end of file From 9204031899db1f672f1ec60090078e2f8c7e637c Mon Sep 17 00:00:00 2001 From: erickbickler Date: Fri, 21 May 2021 16:26:05 -0500 Subject: [PATCH 06/18] added lethal list to json methods --- game/common/game_board.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/game/common/game_board.py b/game/common/game_board.py index 32a85e13..bf89b65b 100644 --- a/game/common/game_board.py +++ b/game/common/game_board.py @@ -37,11 +37,15 @@ def to_json(self): data['width'] = self.width data['height'] = self.height + data['player_list'] = self.player_list data['wall_list'] = self.wall_list data['items_list'] = self.items_list data['upgrades_list'] = self.upgrades_list + data['lethal_list'] = self.lethal_list + data['circle_radius'] = self.circle_radius + data['turn'] = self.turn return data @@ -56,6 +60,8 @@ def from_json(self, data): self.wall_list = data['wall_list'] self.items_list = data['items_list'] self.upgrades_list = data['upgrades_list'] + self.lethal_list = data['lethal_list'] self.circle_radius = data['circle_radius'] + self.turn = data['turn'] \ No newline at end of file From 8c17f2cabe74926f9e76e53ed5bf6474ba93f3ee Mon Sep 17 00:00:00 2001 From: erickbickler Date: Fri, 21 May 2021 17:59:36 -0500 Subject: [PATCH 07/18] add logic for test based on game stats --- game/test_suite/tests/test_game_board.py | 42 +++++++++++++++++++----- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/game/test_suite/tests/test_game_board.py b/game/test_suite/tests/test_game_board.py index df4dd504..dc8e8ea8 100644 --- a/game/test_suite/tests/test_game_board.py +++ b/game/test_suite/tests/test_game_board.py @@ -4,18 +4,42 @@ class TestGameBoard(unittest.TestCase): - def test_circle_radius(self): - # square board test + # square board test + def test_circle_square(self): game_board1 = GameBoard(10, 10) - self.assertGreaterEqual(game_board1.circle_radius, math.sqrt(200)) # should succeed - self.assertAlmostEqual(game_board1.circle_radius, math.sqrt(200)) # if the first test fails, but this one succeeds, then there might be rounding errors + self.assertGreaterEqual(game_board1.circle_radius, .5 * math.sqrt(200)) # should succeed + self.assertAlmostEqual(game_board1.circle_radius, .5 * math.sqrt(200)) # if the first test fails, but this one succeeds, then there might be rounding errors - # rectangular board test, width greater than height + # rectangular board test, width greater than height + def test_circle_rect_width(self): game_board2 = GameBoard(15, 10) - self.assertGreaterEqual(game_board1.circle_radius, math.sqrt(325)) # should succeed - self.assertAlmostEqual(game_board1.circle_radius, math.sqrt(325)) # shows possible rounding errors + self.assertGreaterEqual(game_board1.circle_radius, .5 * math.sqrt(325)) # should succeed + self.assertAlmostEqual(game_board1.circle_radius, .5 * math.sqrt(325)) # shows possible rounding errors - # rectangular board test, height greater than width + # rectangular board test, height greater than width + def test_circle_rect_height(self): game_board3 = GameBoard(10, 15) self.assertGreaterEqual(game_board3.circle_radius, math.sqrt(325)) # should succeed - self.assertAlmostEqual(game_board3.circle_radius, math.sqrt(325)) # shows possible rounding errors \ No newline at end of file + self.assertAlmostEqual(game_board3.circle_radius, math.sqrt(325)) # shows possible rounding errors + + + # check each corner's location, and if y value of corner is >= y value of the circle at that x, then that corner must be inside the circle + def test_circle_game_stats(self): + # formula for circle: x^2 + y^2 = r^2 + def check_corner(corner_x, corner_y, radius): + circle_y = math.sqrt( radius ** 2 - corner_x ** 2 ) + if(circle_y >= corner_y): + return True + return False + + game_board4 = GameBoard() + radius = game_board4.circle_radius + width = game_board4.width + height = game_board4.height + self.assertTrue( + check_corner(width / 2, height / 2, radius ) and # QI + check_corner(-1 * (width / 2), height / 2, radius) and # QII + check_corner(-1 * (width / 2), -1 * (height / 2), radius) and # QIII + check_corner(width / 2, -1 * (height / 2), radius) # QIV + ) + From 824735cc1c5be5cc6209edca4e2c256bf71055ad Mon Sep 17 00:00:00 2001 From: Christopher Parks Date: Sat, 22 May 2021 21:39:56 -0500 Subject: [PATCH 08/18] initial map objects --- game/common/enums.py | 9 +++++++++ game/common/map_object.py | 23 +++++++++++++++++++++++ game/common/player.py | 5 +++-- game/common/stats.py | 10 ++++++++-- game/controllers/master_controller.py | 10 +++++++++- 5 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 game/common/map_object.py diff --git a/game/common/enums.py b/game/common/enums.py index 4e048794..46eef4c4 100644 --- a/game/common/enums.py +++ b/game/common/enums.py @@ -10,3 +10,12 @@ class ObjectType: action = 1 player = 2 game_board = 3 + + +class MapObjectType: + none = 0 + player = 1 + item = 2 + wall = 3 + building = 4 + status_object = 5 diff --git a/game/common/map_object.py b/game/common/map_object.py new file mode 100644 index 00000000..41afdf1c --- /dev/null +++ b/game/common/map_object.py @@ -0,0 +1,23 @@ +from game.common.game_object import GameObject +from game.common.enums import * + +class MapObject(GameObject): + def __init__(self, map_object_type=None, health=None, coordinates=None, hitbox=None): + super().__init__() + # Most likely replace with inheritance later + self.map_object_type = map_object_type + self.health = health + self.coordinates = coordinates + self.hitbox = hitbox + + def to_json(self): + data = super().__init__() + data['map_object_type'] = self.map_object_type + data['coordinates'] = self.coordinates + data['hitbox'] = self.hitbox + + def from_json(self, data): + self.map_object_type = data['map_object_type'] + self.coordinates = data['coordinates'] + self.hitbox = data['hitbox'] + diff --git a/game/common/player.py b/game/common/player.py index 614d0c23..1a0dbe67 100644 --- a/game/common/player.py +++ b/game/common/player.py @@ -6,7 +6,7 @@ class Player(GameObject): - def __init__(self, code=None, team_name=None, action=None): + def __init__(self, code=None, team_name=None, action=None, avatar=None): super().__init__() self.object_type = ObjectType.player @@ -15,6 +15,7 @@ def __init__(self, code=None, team_name=None, action=None): self.team_name = team_name self.code = code self.action = action + self.avatar = avatar def to_json(self): data = super().to_json() @@ -40,4 +41,4 @@ def __str__(self): Team name: {self.team_name} Action: {self.action} """ - return p \ No newline at end of file + return p diff --git a/game/common/stats.py b/game/common/stats.py index 0080d35f..0a5adbe9 100644 --- a/game/common/stats.py +++ b/game/common/stats.py @@ -1,5 +1,11 @@ - +from game.common.enums import * class GameStats: game_board_width = 500 - game_board_height = 500 \ No newline at end of file + game_board_height = 500 + + player_stats = { + 'starting_health': 10, + 'starting_coordinates': [[450, 450], [-450, -450]], + 'hitbox': {'width': 10, 'height': 10} + } diff --git a/game/controllers/master_controller.py b/game/controllers/master_controller.py index b97a03b7..fbb036b4 100644 --- a/game/controllers/master_controller.py +++ b/game/controllers/master_controller.py @@ -2,7 +2,10 @@ from game.common.action import Action from game.common.enums import * +from game.common.stats import GameStats from game.common.player import Player +from game.common.map_object import MapObject + import game.config as config from game.utils.thread import CommunicationThread @@ -19,7 +22,12 @@ def __init__(self): # Receives all clients for the purpose of giving them the objects they will control def give_clients_objects(self, clients): - pass + for i in range(len(clients)): + clients[i].avatar = MapObject( + MapObjectType.player, + GameStats.player_stats['starting_health'], + GameStats.player_stats['starting_coordinates'][i], + GameStats.player_stats['hitbox']) # Generator function. Given a key:value pair where the key is the identifier for the current world and the value is # the state of the world, returns the key that will give the appropriate world information From 3aa2f611d2c823f9943c58507f3553b288184100 Mon Sep 17 00:00:00 2001 From: Christopher Parks Date: Sun, 23 May 2021 16:53:41 -0500 Subject: [PATCH 09/18] removed unnecessary changes --- game/common/enums.py | 9 --------- game/common/map_object.py | 6 ++---- game/common/player.py | 3 +-- game/common/stats.py | 2 +- game/controllers/master_controller.py | 10 +--------- game/test_suite/runner.py | 2 +- game/test_suite/tests/__init__.py | 4 ++-- game/test_suite/tests/test_game_board.py | 8 ++++---- 8 files changed, 12 insertions(+), 32 deletions(-) diff --git a/game/common/enums.py b/game/common/enums.py index 46eef4c4..4e048794 100644 --- a/game/common/enums.py +++ b/game/common/enums.py @@ -10,12 +10,3 @@ class ObjectType: action = 1 player = 2 game_board = 3 - - -class MapObjectType: - none = 0 - player = 1 - item = 2 - wall = 3 - building = 4 - status_object = 5 diff --git a/game/common/map_object.py b/game/common/map_object.py index 41afdf1c..46b0d581 100644 --- a/game/common/map_object.py +++ b/game/common/map_object.py @@ -4,20 +4,18 @@ class MapObject(GameObject): def __init__(self, map_object_type=None, health=None, coordinates=None, hitbox=None): super().__init__() - # Most likely replace with inheritance later - self.map_object_type = map_object_type self.health = health self.coordinates = coordinates self.hitbox = hitbox def to_json(self): data = super().__init__() - data['map_object_type'] = self.map_object_type + data['health'] = self.health data['coordinates'] = self.coordinates data['hitbox'] = self.hitbox def from_json(self, data): - self.map_object_type = data['map_object_type'] + self.health = data['health'] self.coordinates = data['coordinates'] self.hitbox = data['hitbox'] diff --git a/game/common/player.py b/game/common/player.py index 1a0dbe67..1a531462 100644 --- a/game/common/player.py +++ b/game/common/player.py @@ -6,7 +6,7 @@ class Player(GameObject): - def __init__(self, code=None, team_name=None, action=None, avatar=None): + def __init__(self, code=None, team_name=None, action=None): super().__init__() self.object_type = ObjectType.player @@ -15,7 +15,6 @@ def __init__(self, code=None, team_name=None, action=None, avatar=None): self.team_name = team_name self.code = code self.action = action - self.avatar = avatar def to_json(self): data = super().to_json() diff --git a/game/common/stats.py b/game/common/stats.py index 0a5adbe9..6b7c5843 100644 --- a/game/common/stats.py +++ b/game/common/stats.py @@ -6,6 +6,6 @@ class GameStats: player_stats = { 'starting_health': 10, - 'starting_coordinates': [[450, 450], [-450, -450]], + 'starting_coordinates': [[450, 450], [50, 50]], 'hitbox': {'width': 10, 'height': 10} } diff --git a/game/controllers/master_controller.py b/game/controllers/master_controller.py index fbb036b4..b97a03b7 100644 --- a/game/controllers/master_controller.py +++ b/game/controllers/master_controller.py @@ -2,10 +2,7 @@ from game.common.action import Action from game.common.enums import * -from game.common.stats import GameStats from game.common.player import Player -from game.common.map_object import MapObject - import game.config as config from game.utils.thread import CommunicationThread @@ -22,12 +19,7 @@ def __init__(self): # Receives all clients for the purpose of giving them the objects they will control def give_clients_objects(self, clients): - for i in range(len(clients)): - clients[i].avatar = MapObject( - MapObjectType.player, - GameStats.player_stats['starting_health'], - GameStats.player_stats['starting_coordinates'][i], - GameStats.player_stats['hitbox']) + pass # Generator function. Given a key:value pair where the key is the identifier for the current world and the value is # the state of the world, returns the key that will give the appropriate world information diff --git a/game/test_suite/runner.py b/game/test_suite/runner.py index 3c918f41..13afd8fa 100644 --- a/game/test_suite/runner.py +++ b/game/test_suite/runner.py @@ -13,5 +13,5 @@ def main(): if __name__ == '__main__': main() -# To run the test suite, make sure your terminal is in the root directory of the project (the 'byte_le_royale_2021 folder) +# To run the test suite, make sure your terminal is in the root directory of the project (the 'byte_le_royale_2022 folder) # Then, in your terminal, run 'python -m game.test_suite.runner'. This runs this file as a module of the entire project, allowing imports to function properly \ No newline at end of file diff --git a/game/test_suite/tests/__init__.py b/game/test_suite/tests/__init__.py index 0ce74bf5..3aea0e85 100644 --- a/game/test_suite/tests/__init__.py +++ b/game/test_suite/tests/__init__.py @@ -1,8 +1,8 @@ # When you create a new test file, make sure to add it here. # Simply import the class from your file, and then add that class to the '__all__' array. -from game.test_suite.tests.test_example import TestExample +from game.test_suite.tests.test_game_board import TestGameBoard __all__ = [ - 'TestExample' + 'TestGameBoard' ] \ No newline at end of file diff --git a/game/test_suite/tests/test_game_board.py b/game/test_suite/tests/test_game_board.py index dc8e8ea8..b3b5a1d6 100644 --- a/game/test_suite/tests/test_game_board.py +++ b/game/test_suite/tests/test_game_board.py @@ -13,14 +13,14 @@ def test_circle_square(self): # rectangular board test, width greater than height def test_circle_rect_width(self): game_board2 = GameBoard(15, 10) - self.assertGreaterEqual(game_board1.circle_radius, .5 * math.sqrt(325)) # should succeed - self.assertAlmostEqual(game_board1.circle_radius, .5 * math.sqrt(325)) # shows possible rounding errors + self.assertGreaterEqual(game_board2.circle_radius, .5 * math.sqrt(325)) # should succeed + self.assertAlmostEqual(game_board2.circle_radius, .5 * math.sqrt(325)) # shows possible rounding errors # rectangular board test, height greater than width def test_circle_rect_height(self): game_board3 = GameBoard(10, 15) - self.assertGreaterEqual(game_board3.circle_radius, math.sqrt(325)) # should succeed - self.assertAlmostEqual(game_board3.circle_radius, math.sqrt(325)) # shows possible rounding errors + self.assertGreaterEqual(game_board3.circle_radius, .5 * math.sqrt(325)) # should succeed + self.assertAlmostEqual(game_board3.circle_radius, .5 * math.sqrt(325)) # shows possible rounding errors # check each corner's location, and if y value of corner is >= y value of the circle at that x, then that corner must be inside the circle From b004cbfd11e4420482fb05148ee2cbc3a3d01b53 Mon Sep 17 00:00:00 2001 From: Christopher Parks Date: Sun, 23 May 2021 17:49:42 -0500 Subject: [PATCH 10/18] added collidable property to map object --- game/common/map_object.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/game/common/map_object.py b/game/common/map_object.py index 46b0d581..60c047f6 100644 --- a/game/common/map_object.py +++ b/game/common/map_object.py @@ -2,20 +2,23 @@ from game.common.enums import * class MapObject(GameObject): - def __init__(self, map_object_type=None, health=None, coordinates=None, hitbox=None): + def __init__(self, map_object_type=None, health=None, coordinates=None, hitbox=None, collidable=None): super().__init__() self.health = health self.coordinates = coordinates self.hitbox = hitbox + self.collidable = collidable def to_json(self): data = super().__init__() data['health'] = self.health data['coordinates'] = self.coordinates data['hitbox'] = self.hitbox + data['collidable'] = self.collidable def from_json(self, data): self.health = data['health'] self.coordinates = data['coordinates'] self.hitbox = data['hitbox'] + self.collidable = data['collidable'] From 7b1dbb0a5bf4a7e3989525ab84f08debbc7bfa7f Mon Sep 17 00:00:00 2001 From: Christopher Parks Date: Sun, 23 May 2021 23:37:34 -0500 Subject: [PATCH 11/18] fixed mistakes, old implementation --- game/common/map_object.py | 5 ++++- game/common/stats.py | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/game/common/map_object.py b/game/common/map_object.py index 60c047f6..4af906de 100644 --- a/game/common/map_object.py +++ b/game/common/map_object.py @@ -10,13 +10,16 @@ def __init__(self, map_object_type=None, health=None, coordinates=None, hitbox=N self.collidable = collidable def to_json(self): - data = super().__init__() + data = super().to_json() data['health'] = self.health data['coordinates'] = self.coordinates data['hitbox'] = self.hitbox data['collidable'] = self.collidable + return data + def from_json(self, data): + super().from_json(data) self.health = data['health'] self.coordinates = data['coordinates'] self.hitbox = data['hitbox'] diff --git a/game/common/stats.py b/game/common/stats.py index 6b7c5843..3b40d68d 100644 --- a/game/common/stats.py +++ b/game/common/stats.py @@ -1,4 +1,4 @@ -from game.common.enums import * + class GameStats: game_board_width = 500 @@ -6,6 +6,6 @@ class GameStats: player_stats = { 'starting_health': 10, - 'starting_coordinates': [[450, 450], [50, 50]], + 'starting_coordinates': [{'x': 450, 'y': 450}, {'x': 50, 'y': 50}], 'hitbox': {'width': 10, 'height': 10} } From 39a7e48f1a7491e55fa3429f20600b5792e51086 Mon Sep 17 00:00:00 2001 From: Christopher Parks Date: Mon, 24 May 2021 21:30:22 -0500 Subject: [PATCH 12/18] unnecessary parameter removed --- game/common/map_object.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/game/common/map_object.py b/game/common/map_object.py index 4af906de..6ac52587 100644 --- a/game/common/map_object.py +++ b/game/common/map_object.py @@ -2,7 +2,7 @@ from game.common.enums import * class MapObject(GameObject): - def __init__(self, map_object_type=None, health=None, coordinates=None, hitbox=None, collidable=None): + def __init__(self, health=None, coordinates=None, hitbox=None, collidable=None): super().__init__() self.health = health self.coordinates = coordinates From d571b60e04a688be795621c1425403da0e2cd8b3 Mon Sep 17 00:00:00 2001 From: Christopher Parks Date: Thu, 27 May 2021 18:36:37 -0500 Subject: [PATCH 13/18] Created gun object, enums, stats, to string --- game/common/enums.py | 7 ++++++ game/common/gun.py | 47 +++++++++++++++++++++++++++++++++++++++ game/common/map_object.py | 7 ++++++ game/common/stats.py | 19 +++++++++++++++- 4 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 game/common/gun.py diff --git a/game/common/enums.py b/game/common/enums.py index 4e048794..eacee5a2 100644 --- a/game/common/enums.py +++ b/game/common/enums.py @@ -10,3 +10,10 @@ class ObjectType: action = 1 player = 2 game_board = 3 + +class GunType: + none = 0 + handgun = 1 + assault_rifle = 2 + shotgun = 3 + sniper = 4 diff --git a/game/common/gun.py b/game/common/gun.py new file mode 100644 index 00000000..279624f2 --- /dev/null +++ b/game/common/gun.py @@ -0,0 +1,47 @@ +from game.common.game_object import GameObject +from game.common.enums import * +from game.common.stats import GameStats + +class Gun(GameObject): + def __init__(self, gun_type): + super().__init__() + self.gun_type = gun_type + self.damage = GameStats.gun_stats[gun_type]['damage'] + self.fire_rate = GameStats.gun_stats[gun_type]['fire_rate'] + self.cooldown = GameStats.gun_stats[gun_type]['cooldown'] + self.range = GameStats.gun_stats[gun_type]['range'] + self.mag_size = GameStats.gun_stats[gun_type]['mag_size'] + self.reload_speed = GameStats.gun_stats[gun_type]['reload_speed'] + + def to_json(self): + data = super().to_json() + data['gun_type'] = self.gun_type + data['damage'] = self.damage + data['fire_rate'] = self.fire_rate + data['cooldown'] = self.cooldown + data['range'] = self.range + data['mag_size'] = self.mag_size + data['reload_speed'] = self.reload_speed + + return data + + def from_json(self, data): + super().from_json(data) + self.gun_type = data['gun_type'] + self.damage = data['damage'] + self.fire_rate = data['fire_rate'] + self.cooldown = data['cooldown'] + self.range = data['range'] + self.mag_size = data['mag_size'] + self.reload_speed= data['reload_speed'] + + def __str__(self): + return f""" + Gun Type: {self.gun_type} + Damage: {self.damage} + Fire Rate: {self.fire_rate} + Cooldown: {self.cooldown} + Range: {self.range} + Mag Size: {self.mag_size} + Reload Speed: {self.reload_speed} + """ diff --git a/game/common/map_object.py b/game/common/map_object.py index 6ac52587..1e13c054 100644 --- a/game/common/map_object.py +++ b/game/common/map_object.py @@ -25,3 +25,10 @@ def from_json(self, data): self.hitbox = data['hitbox'] self.collidable = data['collidable'] + def __str__(self): + return f""" + Health: {self.health} + Coordinates: {self.coordinates} + Hitbox: {self.hitbox} + Collidable: {self.collidable} + """ diff --git a/game/common/stats.py b/game/common/stats.py index 3b40d68d..35f71a1a 100644 --- a/game/common/stats.py +++ b/game/common/stats.py @@ -1,4 +1,4 @@ - +from game.common.enums import * class GameStats: game_board_width = 500 @@ -9,3 +9,20 @@ class GameStats: 'starting_coordinates': [{'x': 450, 'y': 450}, {'x': 50, 'y': 50}], 'hitbox': {'width': 10, 'height': 10} } + +# Placeholder stats + gun_stats = { + GunType.none: {'damage': 0, 'fire_rate': 0, + 'cooldown': {'max': 0, 'rate': 0}, 'range': 0, 'mag_size': 0, + 'reload_speed': 0}, + GunType.handgun: {'damage': 1, 'fire_rate': 2, + 'cooldown': {'max': 8, 'rate': 2}, 'range': 30, 'mag_size': 13, + 'reload_speed': 3}, + GunType.assault_rifle: {'damage': 1, 'fire_rate': 5, + 'cooldown': {'max': 15, 'rate': 5}, 'range': 50, 'mag_size': 30, + 'reload_speed': 6}, + GunType.shotgun: {'damage': 8, 'fire_rate': 1, 'cooldown': {'max': 1, + 'rate': 1}, 'range': 10, 'mag_size': 2, 'reload_speed': 8}, + GunType.sniper: {'damage': 9, 'fire_rate': 1, 'range': 100, + 'mag_size': 1, 'reload_speed': 8} + } From 60280d3fb790932d84751b8b9d10f6fd365c2847 Mon Sep 17 00:00:00 2001 From: Christopher Parks Date: Fri, 28 May 2021 00:28:39 -0500 Subject: [PATCH 14/18] added pattern, missing cooldown --- game/common/enums.py | 7 +++++++ game/common/gun.py | 4 ++++ game/common/stats.py | 26 ++++++++++++++------------ 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/game/common/enums.py b/game/common/enums.py index eacee5a2..25b6f892 100644 --- a/game/common/enums.py +++ b/game/common/enums.py @@ -17,3 +17,10 @@ class GunType: assault_rifle = 2 shotgun = 3 sniper = 4 + + +class ShotPattern: + none = 0 + single = 1 + multi = 2 + spread = 3 diff --git a/game/common/gun.py b/game/common/gun.py index 279624f2..b4bd8317 100644 --- a/game/common/gun.py +++ b/game/common/gun.py @@ -6,6 +6,7 @@ class Gun(GameObject): def __init__(self, gun_type): super().__init__() self.gun_type = gun_type + self.pattern = GameStats.gun_stats[gun_type]['pattern'] self.damage = GameStats.gun_stats[gun_type]['damage'] self.fire_rate = GameStats.gun_stats[gun_type]['fire_rate'] self.cooldown = GameStats.gun_stats[gun_type]['cooldown'] @@ -16,6 +17,7 @@ def __init__(self, gun_type): def to_json(self): data = super().to_json() data['gun_type'] = self.gun_type + data['pattern'] = self.pattern data['damage'] = self.damage data['fire_rate'] = self.fire_rate data['cooldown'] = self.cooldown @@ -28,6 +30,7 @@ def to_json(self): def from_json(self, data): super().from_json(data) self.gun_type = data['gun_type'] + self.pattern = data['pattern'] self.damage = data['damage'] self.fire_rate = data['fire_rate'] self.cooldown = data['cooldown'] @@ -38,6 +41,7 @@ def from_json(self, data): def __str__(self): return f""" Gun Type: {self.gun_type} + Pattern: {self.pattern} Damage: {self.damage} Fire Rate: {self.fire_rate} Cooldown: {self.cooldown} diff --git a/game/common/stats.py b/game/common/stats.py index 35f71a1a..3ff18333 100644 --- a/game/common/stats.py +++ b/game/common/stats.py @@ -12,17 +12,19 @@ class GameStats: # Placeholder stats gun_stats = { - GunType.none: {'damage': 0, 'fire_rate': 0, - 'cooldown': {'max': 0, 'rate': 0}, 'range': 0, 'mag_size': 0, - 'reload_speed': 0}, - GunType.handgun: {'damage': 1, 'fire_rate': 2, - 'cooldown': {'max': 8, 'rate': 2}, 'range': 30, 'mag_size': 13, - 'reload_speed': 3}, - GunType.assault_rifle: {'damage': 1, 'fire_rate': 5, - 'cooldown': {'max': 15, 'rate': 5}, 'range': 50, 'mag_size': 30, - 'reload_speed': 6}, - GunType.shotgun: {'damage': 8, 'fire_rate': 1, 'cooldown': {'max': 1, - 'rate': 1}, 'range': 10, 'mag_size': 2, 'reload_speed': 8}, - GunType.sniper: {'damage': 9, 'fire_rate': 1, 'range': 100, + GunType.none: {'pattern': ShotPattern.none, 'damage': 0, + 'fire_rate': 0, 'cooldown': {'max': 0, 'rate': 0}, 'range': 0, + 'mag_size': 0, 'reload_speed': 0}, + GunType.handgun: {'pattern': ShotPattern.single, 'damage': 1, + 'fire_rate': 2, 'cooldown': {'max': 8, 'rate': 2}, 'range': 30, + 'mag_size': 13, 'reload_speed': 3}, + GunType.assault_rifle: {'pattern': ShotPattern.multi, 'damage': 1, + 'fire_rate': 5, 'cooldown': {'max': 15, 'rate': 5}, 'range': 50, + 'mag_size': 30, 'reload_speed': 6}, + GunType.shotgun: {'pattern': ShotPattern.spread, 'damage': 8, + 'fire_rate': 1, 'cooldown': {'max': 1, 'rate': 1}, 'range': 10, + 'mag_size': 2, 'reload_speed': 8}, + GunType.sniper: {'pattern': ShotPattern.single, 'damage': 9, + 'fire_rate': 1, 'cooldown': {'max': 1, 'rate': 1}, 'range': 100, 'mag_size': 1, 'reload_speed': 8} } From 283d8dd9fba73b70814f3b332b1414a1490057de Mon Sep 17 00:00:00 2001 From: Christopher Parks Date: Sat, 29 May 2021 00:32:27 -0500 Subject: [PATCH 15/18] added level, inheritance from item --- game/common/enums.py | 5 +++++ game/common/gun.py | 46 +++++++++++++++++++++++++++++++------------- game/common/stats.py | 22 ++++++++++----------- 3 files changed, 49 insertions(+), 24 deletions(-) diff --git a/game/common/enums.py b/game/common/enums.py index 25b6f892..a4d46ac7 100644 --- a/game/common/enums.py +++ b/game/common/enums.py @@ -18,6 +18,11 @@ class GunType: shotgun = 3 sniper = 4 +class GunLevel: + level_zero = 0 + level_one = 1 + level_two = 2 + level_three = 3 class ShotPattern: none = 0 diff --git a/game/common/gun.py b/game/common/gun.py index b4bd8317..81030a07 100644 --- a/game/common/gun.py +++ b/game/common/gun.py @@ -1,51 +1,71 @@ -from game.common.game_object import GameObject from game.common.enums import * from game.common.stats import GameStats +from game.common.items.item import Item -class Gun(GameObject): - def __init__(self, gun_type): +class Gun(Item): + def __init__(self, gun_type, level): super().__init__() self.gun_type = gun_type + # Leveling subject to change + self.level = level self.pattern = GameStats.gun_stats[gun_type]['pattern'] - self.damage = GameStats.gun_stats[gun_type]['damage'] - self.fire_rate = GameStats.gun_stats[gun_type]['fire_rate'] - self.cooldown = GameStats.gun_stats[gun_type]['cooldown'] - self.range = GameStats.gun_stats[gun_type]['range'] - self.mag_size = GameStats.gun_stats[gun_type]['mag_size'] - self.reload_speed = GameStats.gun_stats[gun_type]['reload_speed'] + self.damage = (round(GameStats.gun_stats[gun_type]['damage'] + * (GameStats.gun_stats[gun_type]['level_mod'] ** self.level), 1) + if self.level > GunLevel.level_zero else 0) + self.fire_rate = (round(GameStats.gun_stats[gun_type]['fire_rate'] + * (GameStats.gun_stats[gun_type]['level_mod'] ** self.level)) + if self.level > GunLevel.level_zero else 0) + self.range = (round(GameStats.gun_stats[gun_type]['range'] + * (GameStats.gun_stats[gun_type]['level_mod'] ** self.level)) + if self.level > GunLevel.level_zero else 0) + self.mag_size = (round(GameStats.gun_stats[gun_type]['mag_size'] + * (GameStats.gun_stats[gun_type]['level_mod'] ** self.level)) + if self.level > GunLevel.level_zero else 0) + self.reload_speed = (round(GameStats.gun_stats[gun_type]['reload_speed'] + * (GameStats.gun_stats[gun_type]['level_mod'] ** self.level)) + if self.level > GunLevel.level_zero else 0) + if self.level > GunLevel.level_zero: + self.cooldown = GameStats.gun_stats[gun_type]['cooldown'] + self.cooldown['max'] = round(self.cooldown['max'] + * (GameStats.gun_stats[gun_type]['level_mod'] ** self.level)) + else: + self.cooldown = {'max': 0, 'rate': 0} def to_json(self): data = super().to_json() data['gun_type'] = self.gun_type + data['level'] = self.level data['pattern'] = self.pattern data['damage'] = self.damage data['fire_rate'] = self.fire_rate - data['cooldown'] = self.cooldown data['range'] = self.range data['mag_size'] = self.mag_size data['reload_speed'] = self.reload_speed + data['cooldown'] = self.cooldown return data def from_json(self, data): super().from_json(data) self.gun_type = data['gun_type'] + self.level = data['level'] self.pattern = data['pattern'] self.damage = data['damage'] self.fire_rate = data['fire_rate'] - self.cooldown = data['cooldown'] self.range = data['range'] self.mag_size = data['mag_size'] - self.reload_speed= data['reload_speed'] + self.reload_speed = data['reload_speed'] + self.cooldown = data['cooldown'] def __str__(self): return f""" Gun Type: {self.gun_type} + Level: {self.level} Pattern: {self.pattern} Damage: {self.damage} Fire Rate: {self.fire_rate} - Cooldown: {self.cooldown} Range: {self.range} Mag Size: {self.mag_size} Reload Speed: {self.reload_speed} + Cooldown: {self.cooldown} """ diff --git a/game/common/stats.py b/game/common/stats.py index 3ff18333..29d380c5 100644 --- a/game/common/stats.py +++ b/game/common/stats.py @@ -10,21 +10,21 @@ class GameStats: 'hitbox': {'width': 10, 'height': 10} } -# Placeholder stats +# Placeholder stats, stats may be created for all gun levels gun_stats = { GunType.none: {'pattern': ShotPattern.none, 'damage': 0, - 'fire_rate': 0, 'cooldown': {'max': 0, 'rate': 0}, 'range': 0, - 'mag_size': 0, 'reload_speed': 0}, + 'fire_rate': 0, 'range': 0, 'mag_size': 0, 'reload_speed': 0, + 'cooldown': {'max': 0, 'rate': 0}, 'level_mod': 1}, GunType.handgun: {'pattern': ShotPattern.single, 'damage': 1, - 'fire_rate': 2, 'cooldown': {'max': 8, 'rate': 2}, 'range': 30, - 'mag_size': 13, 'reload_speed': 3}, + 'fire_rate': 2, 'range': 30, 'mag_size': 13, 'reload_speed': 3, + 'cooldown': {'max': 8, 'rate': 2}, 'level_mod': 1.25}, GunType.assault_rifle: {'pattern': ShotPattern.multi, 'damage': 1, - 'fire_rate': 5, 'cooldown': {'max': 15, 'rate': 5}, 'range': 50, - 'mag_size': 30, 'reload_speed': 6}, + 'fire_rate': 5, 'range': 50, 'mag_size': 30, 'reload_speed': 6, + 'cooldown': {'max': 15, 'rate': 5}, 'level_mod': 1.25}, GunType.shotgun: {'pattern': ShotPattern.spread, 'damage': 8, - 'fire_rate': 1, 'cooldown': {'max': 1, 'rate': 1}, 'range': 10, - 'mag_size': 2, 'reload_speed': 8}, + 'fire_rate': 1, 'range': 10, 'mag_size': 2, 'reload_speed': 8, + 'cooldown': {'max': 1, 'rate': 1}, 'level_mod': 1.25}, GunType.sniper: {'pattern': ShotPattern.single, 'damage': 9, - 'fire_rate': 1, 'cooldown': {'max': 1, 'rate': 1}, 'range': 100, - 'mag_size': 1, 'reload_speed': 8} + 'fire_rate': 1, 'range': 100, 'mag_size': 1, 'reload_speed': 8, + 'cooldown': {'max': 1, 'rate': 1}, 'level_mod': 1.25} } From 67ca16714a070942f5fd59cb4061e2f6fa396eeb Mon Sep 17 00:00:00 2001 From: Christopher Parks Date: Sat, 29 May 2021 10:24:41 -0500 Subject: [PATCH 16/18] added object types --- game/common/enums.py | 2 ++ game/common/gun.py | 2 ++ game/common/map_object.py | 2 ++ 3 files changed, 6 insertions(+) diff --git a/game/common/enums.py b/game/common/enums.py index a4d46ac7..77f51340 100644 --- a/game/common/enums.py +++ b/game/common/enums.py @@ -10,6 +10,8 @@ class ObjectType: action = 1 player = 2 game_board = 3 + map_object = 4 + gun = 5 class GunType: none = 0 diff --git a/game/common/gun.py b/game/common/gun.py index 81030a07..f72f6a05 100644 --- a/game/common/gun.py +++ b/game/common/gun.py @@ -5,6 +5,8 @@ class Gun(Item): def __init__(self, gun_type, level): super().__init__() + self.object_type = ObjectType.gun + self.gun_type = gun_type # Leveling subject to change self.level = level diff --git a/game/common/map_object.py b/game/common/map_object.py index 1e13c054..c0dc8780 100644 --- a/game/common/map_object.py +++ b/game/common/map_object.py @@ -4,6 +4,8 @@ class MapObject(GameObject): def __init__(self, health=None, coordinates=None, hitbox=None, collidable=None): super().__init__() + self.object_type = ObjectType.map_object + self.health = health self.coordinates = coordinates self.hitbox = hitbox From 6ce92faec363e5016595a22d222a4963e63d2fbf Mon Sep 17 00:00:00 2001 From: Christopher Parks Date: Sat, 29 May 2021 13:44:31 -0500 Subject: [PATCH 17/18] moved gun object, added object types --- game/common/enums.py | 3 ++- game/common/{ => items}/gun.py | 0 game/common/items/item.py | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) rename game/common/{ => items}/gun.py (100%) diff --git a/game/common/enums.py b/game/common/enums.py index 77f51340..0cd31962 100644 --- a/game/common/enums.py +++ b/game/common/enums.py @@ -11,7 +11,8 @@ class ObjectType: player = 2 game_board = 3 map_object = 4 - gun = 5 + item = 5 + gun = 6 class GunType: none = 0 diff --git a/game/common/gun.py b/game/common/items/gun.py similarity index 100% rename from game/common/gun.py rename to game/common/items/gun.py diff --git a/game/common/items/item.py b/game/common/items/item.py index 5f48bf8b..1e132fa7 100644 --- a/game/common/items/item.py +++ b/game/common/items/item.py @@ -3,6 +3,7 @@ class Item(MapObject): def __init__(self, coordinates, hitbox, health=None, count = 1): super().__init__(health, coordinates, hitbox, True) + self.object_type = ObjectType.item self.count = count def to_json(self): @@ -12,4 +13,4 @@ def to_json(self): def from_json(self, data): super().from_json(data) - self.count = data['count'] \ No newline at end of file + self.count = data['count'] From 8374173c53656230b4fcad4979777756a8c79d63 Mon Sep 17 00:00:00 2001 From: Christopher Parks Date: Sat, 29 May 2021 13:50:41 -0500 Subject: [PATCH 18/18] removed .vs dir --- .vs/byte_le_royale_2022/v16/.suo | Bin 17920 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .vs/byte_le_royale_2022/v16/.suo diff --git a/.vs/byte_le_royale_2022/v16/.suo b/.vs/byte_le_royale_2022/v16/.suo deleted file mode 100644 index f473652bf8696408e0da740e87268b42b8f1c9b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17920 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 Sz(OJ$SCLSSG~ufroA7_XGWW;;