Browse Source

Bot improved, ball kept in game longer now

master
kaqu 1 year ago
parent
commit
09bbbeca9c
  1. 2
      .vscode/launch.json
  2. 2
      README.md
  3. 31
      game_objects/pong_bot.py
  4. 12
      game_objects/pong_constants.py
  5. 6
      game_objects/pong_game.py
  6. 6
      game_objects/pong_globalvars.py
  7. 24
      game_objects/pong_object.py
  8. 52
      game_objects/pong_viewer.py
  9. 12
      pandemic_pong.py
  10. BIN
      pictures/pong_background (copy).png
  11. 2
      pp_player1_bot.sh
  12. 2
      pp_player2_bot.sh

2
.vscode/launch.json

@ -10,7 +10,7 @@
"request": "launch",
"program": "${file}",
//"args": ["--sizeable", "--server"],
"args": ["--sizeable", "--player", "1", "127.0.0.1", "--bot"],
"args": ["--sizeable", "--player", "1", "127.0.0.1", "--botdemo"],
//"args": ["--sizeable", "--viewer", "127.0.0.1"],
"console": "integratedTerminal"
}

2
README.md

@ -174,3 +174,5 @@ After some 2-5s this effect will disappear. Currently, there is no clean initial
* Maybe HTTP streaming shall be moved to raw TCP streaming ...
* Game mechanics: Maybe introduce an incubation time?
* Write a better ('invincible'?) attacking - horizontal movement - bot ...

31
game_objects/pong_bot.py

@ -22,12 +22,12 @@ lastcolor = 0 # No color assumed
def calculate_target(msg, x, y, delta_x, delta_y):
#print("Ball({0}): x={1:.0f} y={2:.0f} (delta_x={3:.0f} delta_y={4:.0f})".format(msg, x, y, delta_x, delta_y))
if delta_y < 0: # /\
ny = abs(y / delta_y)
ny = abs((y - pgc.GAMEAREA_MIN_Y) / delta_y)
elif delta_y > 0: # \/
ny = abs((pgc.GAMEAREA_MAX_Y - y) / delta_y)
if delta_x < 0: # <- (Bot #1)
nx = abs(x / delta_x)
nx = abs((x - pgc.GAMEAREA_MIN_X) / delta_x)
else: # -> (Bot #2)
nx = abs((pgc.GAMEAREA_MAX_X - x) / delta_x)
@ -45,7 +45,7 @@ def calculate_target(msg, x, y, delta_x, delta_y):
def bot_game_logic(ball, player):
"""Actual PLAY state player bot logic"""
global resenddelay, back_to_neutral_y, lastcolor
if resenddelay > 0:
resenddelay -= 1
return 0, 0, 0
@ -98,33 +98,28 @@ def bot_game_logic(ball, player):
back_to_neutral_y = True
return 3, 0, 1 # Going up
else: # Ball approaching!
""" Old logic
if (ball.y + ball.h/2) > (player.y + 3*player.h/4): # Ball is below player?
#print("ball below, going down")
back_to_neutral_y = True
return 3, 255, 1
elif (ball.y + ball.h/2) < (player.y + player.h/4): # Ball is above player?
#print("ball above, going up")
back_to_neutral_y = True
return 3, 0, 1
"""
xt, yt = calculate_target("1", ball.x, ball.y, ball.delta_x, ball.delta_y) # Potential wall contact point calculation
xt, yt = calculate_target("1", ball.x + ball.w/2, ball.y + ball.h/2, ball.delta_x, ball.delta_y) # Potential wall contact point calculation
pgv.xt1 = xt
pgv.yt1 = yt
if player.player_index == 1: # Bot 1
if xt <= pgc.GAMEAREA_MIN_X: # (d) Direct player approach
pass # Calculate crossing where x=0
else: # Wall contact (a) or (c)
if ball.delta_y != 0: # (c) > 0, (a) < 0
_, yt = calculate_target("2", xt, yt, ball.delta_x, -ball.delta_y) # Invert y movement
xt, yt = calculate_target("2", xt, yt, ball.delta_x, -ball.delta_y) # Invert y movement
else: # Horizontal movement
yt = ball.y # Bot target height
yt = ball.y + ball.h/2 # Bot target height
else: # Bot #2
if xt >= pgc.GAMEAREA_MAX_X: # (b) Direct player approach
pass # Calculate crossing where x=xmax
else: # Wall contact (a) or (c)
if ball.delta_y != 0: # (c) > 0, (a) < 0
_, yt = calculate_target("2", xt, yt, ball.delta_x, -ball.delta_y) # Invert y movement
xt, yt = calculate_target("2", xt, yt, ball.delta_x, -ball.delta_y) # Invert y movement
else: # Horizontal movement
yt = ball.y # Bot target height
yt = ball.y + ball.h/2 # Bot target height
pgv.xt2 = xt
pgv.yt2 = yt
if yt > (player.y + 3*player.h/4): # Target is below player?
#print("Target below, going down")

12
game_objects/pong_constants.py

@ -7,6 +7,8 @@ Pandemic Pong global constants
"""
from PyQt5.QtCore import Qt # Color def. import
DEVLOCAL = False # TODO: For client/server local development set to 'True'! For publication to 'False'!
"""Buttons in 'state<n>'"""
@ -27,6 +29,14 @@ COL_GREEN = 2 # Virus color
COL_RED = 3 # Virus color
COL_YELLOW = 4 # virus color
colormap = { # Map game to Qt colors
COL_WHITE : Qt.white,
COL_BLUE : Qt.blue,
COL_GREEN : Qt.green,
COL_RED : Qt.red,
COL_YELLOW: Qt.yellow
}
"""Infectiousness time"""
COLORDELAY = 100
@ -82,7 +92,7 @@ sounds = {
""" Game area dimensions, shall be mutable to adjust for window resize (later)"""
GAMEAREA_MIN_X = 0 # Game area left border
GAMEAREA_MAX_X = 1920 # Assume FHD resolution by default
GAMEAREA_MIN_Y = 15 # Game area top border
GAMEAREA_MIN_Y = 25 # Game area top border
GAMEAREA_MAX_Y = 940 # Game area bottom range
"""Fine tuning thread yield"""

6
game_objects/pong_game.py

@ -172,6 +172,7 @@ class PongGame:
self.playsound = pgc.PLAYERCONTACTSOUND
def pong_game(self, ball, player1, player2):
"""Play the game!"""
if (pgv.bIsServer == True) or (pgv.bIsLocal == True): # Game engine runs locally or on server only!
if self.game_fsm(player1, player2) == False: # Exit
@ -203,9 +204,10 @@ class PongGame:
self.crashvectors(ball, player1, player2)
# 4. Adjust object positions (ball & potentially others ...)
rc = ball.eval_object()
rc = ball.eval_object(player1, player2)
if rc != 0: # Miss left(-1) or right(1)
if rc == -1: # Player #2: +1
# TODO: Check horizontal clear, invert X?!
if rc == -1: # Player #2: +1
player2.score = player2.score + 1
ball.reinit(10 + (random() - 0.5) * 4, (random() - 0.5) * 10)
self.playsound = pgc.PLAYERMISSSOUND

6
game_objects/pong_globalvars.py

@ -12,3 +12,9 @@ bSizeable = False # Qt5 window sizeable
bIsServer = False # Global server indication
bIsViewer = False # Global viewer indication
bIsLocal = True # Local game only, by default
bBotDemo = False # Show prognosis data
xt1 = 0 # Wall contact assumption or direct approach
yt1 = 0
xt2 = 0 # Direct approach point
yt2 = 0

24
game_objects/pong_object.py

@ -39,18 +39,30 @@ class PongObject:
self.color = pgc.COL_WHITE
self.delay = 0
def eval_object(self):
def eval_object(self, player1, player2):
"""Object movement w/ sound support"""
bChanged = 0
sum_x = self.x + self.delta_x
sum_y = self.y + self.delta_y
if sum_x < pgc.GAMEAREA_MIN_X:
bChanged = -1 # Miss left
elif sum_x + self.w > pgc.GAMEAREA_MAX_X:
bChanged = 1 # Miss right
# Left/right: Out-of-game area check
if sum_x < pgc.GAMEAREA_MIN_X: # Player #1 side
if (sum_y < player1.y) or (sum_y > (player1.y + player1.h)): # Out of player range?
bChanged = -1 # Miss left
else: # Correct player #1 'passed'
sum_x = pgc.GAMEAREA_MIN_X + player1.w
self.delta_x = -self.delta_x
self.playsound = pgc.PLAYERCONTACTSOUND
elif (sum_x + self.w) > pgc.GAMEAREA_MAX_X: # Player #2 side
if (sum_y < player2.y) or (sum_y > (player2.y + player2.h)): # Out of player range?
bChanged = 1 # Miss right
else: # Correct player #2 'passed' ...
sum_x = pgc.GAMEAREA_MAX_X - player2.w
self.delta_x = -self.delta_x
self.playsound = pgc.PLAYERCONTACTSOUND
# Wall contact check
if sum_y < pgc.GAMEAREA_MIN_Y:
sum_y = pgc.GAMEAREA_MIN_Y
self.delta_y = -self.delta_y

52
game_objects/pong_viewer.py

@ -148,40 +148,20 @@ class pongWindow(QMainWindow):
# Ball gives NO indication ...
painter.drawRect(int(self.ball.x * scale_x), int(self.ball.y * scale_y), int(self.ball.w * scale_x), int(self.ball.h * scale_y)) # Ball
if self.player1.color == pgc.COL_WHITE:
painter.setPen(QPen(Qt.white, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
painter.setBrush(QBrush(Qt.white, Qt.SolidPattern)) # Fill
elif self.player1.color == pgc.COL_BLUE:
painter.setPen(QPen(Qt.blue, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
painter.setBrush(QBrush(Qt.blue, Qt.SolidPattern)) # Fill
elif self.player1.color == pgc.COL_GREEN:
painter.setPen(QPen(Qt.green, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
painter.setBrush(QBrush(Qt.green, Qt.SolidPattern)) # Fill
elif self.player1.color == pgc.COL_RED:
painter.setPen(QPen(Qt.red, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
painter.setBrush(QBrush(Qt.red, Qt.SolidPattern)) # Fill
elif self.player1.color == pgc.COL_YELLOW:
painter.setPen(QPen(Qt.yellow, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
painter.setBrush(QBrush(Qt.yellow, Qt.SolidPattern)) # Fill
painter.drawRect(int(self.player1.x * scale_x), int(self.player1.y * scale_y), int(self.player1.w * scale_x), int(self.player1.h * scale_y)) # Player left
if self.player2.color == pgc.COL_WHITE:
painter.setPen(QPen(Qt.white, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
painter.setBrush(QBrush(Qt.white, Qt.SolidPattern)) # Fill
elif self.player2.color == pgc.COL_BLUE:
painter.setPen(QPen(Qt.blue, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
painter.setBrush(QBrush(Qt.blue, Qt.SolidPattern)) # Fill
elif self.player2.color == pgc.COL_GREEN:
painter.setPen(QPen(Qt.green, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
painter.setBrush(QBrush(Qt.green, Qt.SolidPattern)) # Fill
elif self.player2.color == pgc.COL_RED:
painter.setPen(QPen(Qt.red, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
painter.setBrush(QBrush(Qt.red, Qt.SolidPattern)) # Fill
elif self.player2.color == pgc.COL_YELLOW:
painter.setPen(QPen(Qt.yellow, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
painter.setBrush(QBrush(Qt.yellow, Qt.SolidPattern)) # Fill
painter.drawRect(int(self.player2.x * scale_x), int(self.player2.y * scale_y), int(self.player2.w * scale_x), int(self.player2.h * scale_y)) # Player right
if pgv.bBotDemo == True: # Show prognosis target
if ((len(self.player1.player_server) > 0) and (self.ball.delta_x < 0)) or ((len(self.player2.player_server) > 0) and (self.ball.delta_x > 0)):
painter.drawLine(int((self.ball.x+self.ball.w/2) * scale_x), int((self.ball.y+self.ball.h/2) * scale_y), int(pgv.xt1 * scale_x), int(pgv.yt1 * scale_y))
if (pgv.xt2 != pgv.xt1) or (pgv.yt2 != pgv.yt1): # w/ reflection!
painter.drawLine(int(pgv.xt1 * scale_x), int(pgv.yt1 * scale_y), int(pgv.xt2 * scale_x), int(pgv.yt2 * scale_y))
painter.setPen(QPen(pgc.colormap[self.player1.color], 1, Qt.SolidLine)) # Color/Linewidth/Pattern
painter.setBrush(QBrush(pgc.colormap[self.player1.color], Qt.SolidPattern)) # Fill
painter.drawRect(int(self.player1.x * scale_x), int(self.player1.y * scale_y), int(self.player1.w * scale_x), int(self.player1.h * scale_y)) # Player left
painter.setPen(QPen(pgc.colormap[self.player2.color], 1, Qt.SolidLine)) # Color/Linewidth/Pattern
painter.setBrush(QBrush(pgc.colormap[self.player2.color], Qt.SolidPattern)) # Fill
painter.drawRect(int(self.player2.x * scale_x), int(self.player2.y * scale_y), int(self.player2.w * scale_x), int(self.player2.h * scale_y)) # Player right
painter.setPen(QPen(Qt.white, 1, Qt.SolidLine)) # Reset standard colour
painter.setBrush(QBrush(Qt.white, Qt.SolidPattern))
@ -194,9 +174,9 @@ class pongWindow(QMainWindow):
# Score player #2
painter.drawText(int((pgc.GAMEAREA_MAX_X - 840) * scale_x), int(154 * scale_y), "{}".format(self.player2.score))
# Indicate Button states
draw_buttonstate(60, 50, self.player1, painter, scale_x, scale_y)
draw_buttonstate(pgc.GAMEAREA_MAX_X - 180, 50, self.player2, painter, scale_x, scale_y)
# Indicate Button states (not used)
#draw_buttonstate(60, 50, self.player1, painter, scale_x, scale_y)
#draw_buttonstate(pgc.GAMEAREA_MAX_X - 180, 50, self.player2, painter, scale_x, scale_y)
elif self.game.state == pgc.STATE_GAMERESULTS: # Display winner of this game
painter.setFont(fntMedium)
if self.player1.score > 9:

12
pandemic_pong.py

@ -66,10 +66,14 @@ if __name__ == '__main__':
if len(sys.argv) == 6: # Bot option?
if sys.argv[5] == "--bot":
bot_msg = "bot"
if player_index == 2:
bIsBot2 = True
else: # Player 1 bot assumed
bIsBot1 = True
pgv.bBotDemo = False
elif sys.argv[5] == "--botdemo":
bot_msg = "botdemo"
pgv.bBotDemo = True
if player_index == 2:
bIsBot2 = True
else: # Player 1 bot assumed
bIsBot1 = True
print("*** PANDEMIC PONG (player #{} {} talking to game server @{}) ***".format(player_index, bot_msg, player_server))
if pgc.DEVLOCAL == True:
debug_x = int(pgc.GAMEAREA_MAX_X / 3 * 4 * (player_index-1)) # Left(0) or right top window

BIN
pictures/pong_background (copy).png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

2
pp_player1_bot.sh

@ -3,6 +3,6 @@ if [ -z $1 ]; then
echo "usage: ./pp_player1_bot.sh <gameserver>"
exit
fi
# use --botdemo instead of --bot to show calculated target position
./pandemic_pong.py --sizeable --player 1 $1 --bot
echo "Pandemic Pong player #1 bot client terminated."

2
pp_player2_bot.sh

@ -3,6 +3,6 @@ if [ -z $1 ]; then
echo "usage: ./pp_player2_bot.sh <gameserver>"
exit
fi
# use --botdemo instead of --bot to show calculated target position
./pandemic_pong.py --sizeable --player 2 $1 --bot
echo "Pandemic Pong player #2 bot client terminated."
Loading…
Cancel
Save