I am creating a 2 player same-screen game which uses both players playing on the same computer, both using the keyboard. I am struggling to find a way to code it in OOP so that once one of the player's health is below or equal to 0, both player positions are reset back to the starting position (standard x and y coordinate) and score being incremented by 1 for the player which was left standing. Instead, the players' health reaches 0 and the character disappears off screen but can still shoot, run, jump etc. I intend on this being an instantaneous change to the next round, with perhaps a second delay between the health reaching 0 and the next round starting. Here is the code relevant to my problem:
class Player:
def __init__(self, x, y, width, height, speed, images_right, images_left, idle_image):
self.x = x
self.y = y
self.width = width
self.height = height
self.speed = speed
self.left = False
self.right = False
self.jump_status = False
self.jump_time = 10
self.anim_num = 0
self.images_right = images_right
self.images_left = images_left
self.idle_image = idle_image
self.hitbox = (self.x + 17, self.y + 11, 29, 52)
self.health = 10
self.visible = True
self.maxhealth = 10
self.score = 0
self.start = (x,y)
def hit(self):
if self.health > 0:
self.health -= 1
else:
self.visible = False
print('hit')
class ResettableSprite:
def __init__(self, idle_image, x, y):
self.idle_image = idle_image
self.rect = self.image.get_rect()
self.start_x = x
self.start_y = y
self.reset()
def reset(self):
self.rect.x = self.start_x
self.rect.y = self.start_y
self.health = Player.maxhealth
player1 = Player(200, 317, 64, 64, 10, walkRight, walkLeft, char)
player2 = Player(500, 285, 92, 85, 10, walkRight2, walkLeft2, dragon)
I have tried to create a 'ResettableSprite' class and then allow self.start coordinates to equal the original x coordinates used when loading in the players as soon as the program is run. However, this does not proivde an error message, but rather continues to allow both players' health to reach 0, allow their character to disappear off the screen, but still allowing them to run, jump and shoot as if they still had health remaining.
I am creating a 2 player same-screen game which uses both players playing on the same computer, both using the keyboard. I am struggling to find a way to code it in OOP so that once one of the player's health is below or equal to 0, both player positions are reset back to the starting position (standard x and y coordinate) and score being incremented by 1 for the player which was left standing. Instead, the players' health reaches 0 and the character disappears off screen but can still shoot, run, jump etc. I intend on this being an instantaneous change to the next round, with perhaps a second delay between the health reaching 0 and the next round starting. Here is the code relevant to my problem:
class Player:
def __init__(self, x, y, width, height, speed, images_right, images_left, idle_image):
self.x = x
self.y = y
self.width = width
self.height = height
self.speed = speed
self.left = False
self.right = False
self.jump_status = False
self.jump_time = 10
self.anim_num = 0
self.images_right = images_right
self.images_left = images_left
self.idle_image = idle_image
self.hitbox = (self.x + 17, self.y + 11, 29, 52)
self.health = 10
self.visible = True
self.maxhealth = 10
self.score = 0
self.start = (x,y)
def hit(self):
if self.health > 0:
self.health -= 1
else:
self.visible = False
print('hit')
class ResettableSprite:
def __init__(self, idle_image, x, y):
self.idle_image = idle_image
self.rect = self.image.get_rect()
self.start_x = x
self.start_y = y
self.reset()
def reset(self):
self.rect.x = self.start_x
self.rect.y = self.start_y
self.health = Player.maxhealth
player1 = Player(200, 317, 64, 64, 10, walkRight, walkLeft, char)
player2 = Player(500, 285, 92, 85, 10, walkRight2, walkLeft2, dragon)
I have tried to create a 'ResettableSprite' class and then allow self.start coordinates to equal the original x coordinates used when loading in the players as soon as the program is run. However, this does not proivde an error message, but rather continues to allow both players' health to reach 0, allow their character to disappear off the screen, but still allowing them to run, jump and shoot as if they still had health remaining.
Share Improve this question edited Mar 11 at 5:41 Rabbid76 211k30 gold badges159 silver badges200 bronze badges asked Mar 10 at 19:18 user29961654user29961654 132 bronze badges 2- 2 What you need is a "game" object that owns both players. The "game" object can monitor the player states, and send "resets" if the need arises. You could even use callbacks, to have the player objects send a message to the game when health reached 0, but monitoring is probably OK. – Tim Roberts Commented Mar 10 at 19:22
- Thanks, I will attempt this now @TimRoberts – user29961654 Commented Mar 10 at 19:28
2 Answers
Reset to default -1When a player's health reaches 0, you set visible = False
but don't trigger a reset
What I think you can do in hit
function is something like this:
def hit(self):
if self.health > 0:
self.health -= 1
else:
self.visible = False
if self == player1 and player2.health > 0:
player2.score += 1
self.reset()
player2.reset()
elif self == player2 and player1.health > 0:
player1.score += 1
self.reset()
player1.reset()
print('hit')
There's not the controlling code in the question, so this answer is based on what's presented, and is thus speaking in ignorance.
Based on what's provided, the Player
object does not encapsulate all the operations on the Player
data. I expect that later on in the code, the Player.x
and Player.y
(etc.) are modified without the control of the object. By this I mean, the main loop changes Player.x
directly. Whereas this code should be part of the Player object, and updated indirectly. It's basically what you're doing in Player.hit()
but for everything involving a Player object.
For example, moving the player:
class Player:
def __init__(self, x, y, width, height, speed, images_right, images_left, idle_image):
self.x = x
self.y = y
self.width = width
# [...]
def move( self, dx, dy ):
self.x += dx
self.y += dy
# TODO add screen constraints to movement
Not just for Player.move()
but for all the player functions.
Once all this functionality is encapsulated, the Player
object itself can decide what to do when "dead", and ignore handling of inputs:
class Player:
# [...]
def isAlive( self ):
return ( self.health > 0 )
def move( self, dx, dy ):
if ( self.isAlive() ):
self.x += dx
self.y += dy
# TODO add screen constraints to movement
def fire( self ):
if ( self.isAlive() ):
# TODO create bullet
def draw( self, screen ):
if ( self.isAlive() ):
screen.blit( self.image, self.rect )
else:
screen.blit( self.tombstone_image, self.rect )
The point of Object Oriented programming is to encapsulate the operations on the Object's data inside the object itself. So no-where except inside the object does the data get used or modified. The code doesn't draw( player1.image )
, it calls player1.draw( screen )
, and then the Player object can look at its situation, and draw (or not) the appropriate image; accept or not-accept movement input, etc. etc.
This allows your main loop to test if ( player1.isAlive() and player2.isAlive() )
acting accordingly.
So to reset the health of the player, add a function for that:
def setHealth( self, hp:10 ):
self.health = hp
But maybe a "reset" would be better:
def reset( self, x=Player.STARTX, y=Player.STARTY, hp=10 ):
self.health = hp
self.x = x
self.y = y