Compare commits

...

10 Commits

Author SHA1 Message Date
PAlexanderFranklin
7251a27183 Add virtual environment and requirements file 2023-11-11 01:48:23 -08:00
PAlexanderFranklin
da052ac6f0 Add pathing enemies to pathmap, etc. 2023-05-19 05:20:28 -07:00
PAlexanderFranklin
0b4565f504 Add Mage 2023-05-18 18:31:56 -07:00
PAlexanderFranklin
1955395811 Improve ai 2023-05-18 03:52:06 -07:00
PAlexanderFranklin
5ecef4efba add circle sprites, refactor movement randomization 2023-05-18 03:43:33 -07:00
PAlexanderFranklin
d169ed2fbd Fix pathing 2023-05-18 03:42:58 -07:00
PAlexanderFranklin
de08303bb0 Improve ai 2023-05-18 02:40:51 -07:00
PAlexanderFranklin
0add18a31d Add new enemy type that doesn't work 2023-05-18 01:57:15 -07:00
PAlexanderFranklin
5973675c51 refactor OOBounds, change gore color, other 2023-05-18 01:03:23 -07:00
PAlexanderFranklin
0cff07658f Fix block pull out of bounds check 2023-05-18 00:56:24 -07:00
9 changed files with 195 additions and 84 deletions

3
.gitignore vendored
View File

@ -1 +1,2 @@
__pycache__
__pycache__
venv

View File

@ -17,11 +17,6 @@ def main():
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((screen_width,screen_height))
pygame.display.set_caption('Arctic Masher')
bottomBar = pygame.Rect(0, screen_height - bottomBarHeight, screen_width, bottomBarHeight)
players["1"] = (Player(
"1",
5,
@ -53,7 +48,7 @@ def main():
(pygame.K_KP_1, "sw"),
(pygame.K_KP_4, "w"),
(pygame.K_KP_7, "nw"),
(pygame.K_KP_0, "p"),
(pygame.K_RSHIFT, "p"),
],
))
# players["3"] = (Player(
@ -74,6 +69,12 @@ def main():
# ],
# ))
gameWindow = pygame.display.set_mode((screen_width,screen_height))
pygame.display.set_caption('Arctic Masher')
bottomBar = pygame.Rect(0, screen_height - bottomBarHeight, screen_width, bottomBarHeight)
mapgen.generateMap()
sprite_sheet_image = pygame.image.load('assets/penguin.png').convert_alpha()
@ -86,6 +87,7 @@ def main():
return image
frame_0 = get_image(sprite_sheet_image, 0, 0, 32, 32, (tile-2)/32, black)
frame_1 = get_image(sprite_sheet_image, 0, 32, 32, 32, (tile-2)/32, black)
frame_4 = get_image(sprite_sheet_image, 32, 0, 32, 32, (tile-2)/32, black)
game_font = pygame.font.Font("freesansbold.ttf",32)
@ -105,23 +107,24 @@ def main():
enemy.runAI()
# Rendering
screen.fill(bg_color)
pygame.draw.rect(screen, bar_color, bottomBar)
gameWindow.fill(bg_color)
pygame.draw.rect(gameWindow, bar_color, bottomBar)
for column in gameMap:
for spot in column:
if not spot:
continue
elif isinstance(spot, Block):
pygame.draw.rect(screen, spot.color, spot.sprite)
pygame.draw.rect(gameWindow, spot.color, spot.sprite)
elif isinstance(spot, Enemy):
screen.blit(frame_4, ((tile*spot.renderPos[0])+2, (tile*spot.renderPos[1])+2))
spot.renderPos = ((spot.x - spot.renderPos[0])/3 + spot.renderPos[0], (spot.y - spot.renderPos[1])/3 + spot.renderPos[1])
gameWindow.blit(spot.sprite, ((tile*spot.renderPos[0])+2, (tile*spot.renderPos[1])+2))
elif isinstance(spot, Player):
screen.blit(frame_0, ((tile*spot.renderPos[0])+2, (tile*spot.renderPos[1])+2))
spot.renderPos = ((spot.x - spot.renderPos[0])/3 + spot.renderPos[0], (spot.y - spot.renderPos[1])/3 + spot.renderPos[1])
gameWindow.blit(frame_0, ((tile*spot.renderPos[0])+2, (tile*spot.renderPos[1])+2))
scoreSurface = game_font.render(f'player {spot.id} kills: {spot.kills} lives: {spot.lives}', False, black)
screen.blit(scoreSurface, (500*int(spot.id) - 400, screen_height - bottomBarHeight + 20))
gameWindow.blit(scoreSurface, (500*int(spot.id) - 400, screen_height - bottomBarHeight + 20))
try:
spot.renderPos = ((spot.x - spot.renderPos[0])/3 + spot.renderPos[0], (spot.y - spot.renderPos[1])/3 + spot.renderPos[1])
except:
pass
pygame.display.flip()
clock.tick(60)

View File

@ -2,6 +2,7 @@ import pygame
import uuid
from globals import *
from utilities import *
from enemies import *
class Block:
@ -15,7 +16,7 @@ class Block:
self.sprite = pygame.Rect((x*tile) + 2, (y*tile) + 2, tile - 2, tile - 2)
def pushed(self, x, y, caller, pusher):
if self.x + x > tileCountx - 1 or self.y + y > tileCounty - 1 or self.x + x < 0 or self.y + y < 0:
if checkOOBounds((self.x + x, self.y + y)):
raise Exception("Cannot push off edge!")
if gameMap[self.x + x][self.y + y]:
gameMap[self.x + x][self.y + y].pushed(x, y, self, pusher)
@ -29,6 +30,8 @@ class Block:
def pulled(self, x, y):
for i in range(-1,2):
for j in range(-1,2):
if checkOOBounds((self.x + i, self.y + j)):
continue
if hasattr(gameMap[self.x + i][self.y + j], "ENEMY"):
raise Exception("Cannot pull a block that is touching an enemy")
gameMap[self.x][self.y] = False

View File

@ -3,6 +3,7 @@ import uuid
import random
from globals import *
from utilities import *
from player import *
from blocks import *
@ -13,9 +14,28 @@ def findClosestPlayer(x, y):
distance = max(abs(difference[0]), abs(difference[1]))
if distance > closestPlayerPosition["distance"]:
continue
closestPlayerPosition = {"difference": difference, "distance": distance}
closestPlayerPosition = {"difference": difference, "distance": distance, "player": player}
return closestPlayerPosition
def randomizeMovement(weightsx, weightsy, diff, wrongChance):
weightsx = [-diff[0], abs(diff[1])+0.1, diff[0]]
if weightsx[0] < 0:
weightsx[0] = weightsx[2]*wrongChance
elif weightsx[2] < 0:
weightsx[2] = weightsx[0]*wrongChance
else:
weightsx[0] = max(weightsx[1]/(15.1-weightsx[1]*0.5), 1)
weightsx[2] = weightsx[0]
weightsy = [-diff[1], abs(diff[0])+0.1, diff[1]]
if weightsy[0] < 0:
weightsy[0] = weightsy[2]*wrongChance
elif weightsy[2] < 0:
weightsy[2] = weightsy[0]*wrongChance
else:
weightsy[0] = max(weightsy[1]/(15.1-weightsy[1]*0.5), 1)
weightsy[2] = weightsy[0]
return (weightsx, weightsy)
class Enemy:
def __init__(self, id, x, y):
self.id = id
@ -23,25 +43,27 @@ class Enemy:
self.x = x
self.y = y
self.renderPos = (x,y)
self.AITime = random.randint(350, 600)
# self.AITime = random.randint(350, 600)
self.AITime = random.randint(10, 50)
self.deathColor = white
self.sprite = pygame.Surface((32,32), pygame.SRCALPHA)
pygame.draw.circle(self.sprite, white, (16,16), 10)
def die(self):
del enemies[self.id]
def pushed(self, x, y, caller, pusher):
if hasattr(pusher, "PLAYER") and hasattr(caller, "BLOCK"):
wallCrush = self.x + x > tileCountx - 1 or self.y + y > tileCounty - 1 or self.x + x < 0 or self.y + y < 0
if wallCrush or hasattr(gameMap[self.x + x][self.y + y], "BLOCK"):
if checkOOBounds((self.x + x, self.y + y)) or hasattr(gameMap[self.x + x][self.y + y], "BLOCK"):
pusher.kills += 1
caller.color = random.choice([grey, green])
caller.color = self.deathColor
self.die()
return
raise Exception("Not crushing enemy!")
def move(self, x, y):
try:
if self.x + x > tileCountx - 1 or self.y + y > tileCounty - 1 or self.x + x < 0 or self.y + y < 0:
if checkOOBounds((self.x + x, self.y + y)):
raise Exception("Cannot move off edge!")
if gameMap[self.x + x][self.y + y]:
if hasattr(gameMap[self.x + x][self.y + y], "PLAYER"):
@ -59,26 +81,82 @@ class Enemy:
self.AITime -= 1
if self.AITime < 1:
try:
closestPlayer = findClosestPlayer(self.x, self.y)
weightsx = [-closestPlayer["difference"][0], abs(closestPlayer["difference"][1]), closestPlayer["difference"][0]]
if weightsx[0] < 0:
weightsx[0] = weightsx[2]/6
elif weightsx[2] < 0:
weightsx[2] = weightsx[0]/6
else:
weightsx[0] = weightsx[1]/8
weightsx[2] = weightsx[1]/8
weightsy = [-closestPlayer["difference"][1], abs(closestPlayer["difference"][0]), closestPlayer["difference"][1]]
if weightsy[0] < 0:
weightsy[0] = weightsy[2]/6
elif weightsy[2] < 0:
weightsy[2] = weightsy[0]/6
else:
weightsy[0] = weightsy[1]/8
weightsy[2] = weightsy[1]/8
diff = findClosestPlayer(self.x, self.y)["difference"]
weightsx = [1,1,1]
weightsy = [1,1,1]
randomWeights = randomizeMovement(weightsx, weightsy, diff, 0.15)
weightsx = randomWeights[0]
weightsy = randomWeights[1]
movementx = random.choices([-1, 0, 1], weightsx)[0]
movementy = random.choices([-1, 0, 1], weightsy)[0]
self.move(movementx, movementy)
self.AITime = random.randint(150, 200)
except Exception as error:
pass
class Smart(Enemy):
def __init__(self, id, x, y):
Enemy.__init__(self, id, x, y)
self.SMART = True
self.usesPathMap = True
self.deathColor = red
self.trackedPlayer = False
self.trackingCounter = 0
self.sprite = pygame.Surface((32,32), pygame.SRCALPHA)
pygame.draw.circle(self.sprite, red, (16,16), 12)
def runAI(self):
self.AITime -= 1
if self.AITime < 1:
try:
if self.trackingCounter < 1:
self.AITime = random.randint(150, 250)
self.trackingCounter = 9
self.trackedPlayer = False
elif self.trackedPlayer and self.trackedPlayer["player"].alive:
pathMap = self.trackedPlayer["player"].pathMap
weightsx = [1,1,1]
weightsy = [1,1,1]
if pathMap[self.x][self.y]:
fastDir = pathMap[self.x][self.y][2]
weightsx[1 + fastDir[0]] = 30
weightsy[1 + fastDir[1]] = 30
else:
randomWeights = randomizeMovement(weightsx, weightsy, self.trackedPlayer["difference"], 0.32)
weightsx = randomWeights[0]
weightsy = randomWeights[1]
movementx = random.choices([-1, 0, 1], weightsx)[0]
movementy = random.choices([-1, 0, 1], weightsy)[0]
self.move(movementx, movementy)
self.trackingCounter -= 1
self.AITime = random.randint(10, 15)
else:
closestPlayer = findClosestPlayer(self.x, self.y)
self.trackedPlayer = closestPlayer
self.AITime = random.randint(10, 15)
except Exception as error:
pass
class Mage(Enemy):
def __init__(self, id, x, y):
Enemy.__init__(self, id, x, y)
self.deathColor = purple
self.sprite = pygame.Surface((32,32), pygame.SRCALPHA)
pygame.draw.circle(self.sprite, purple, (16,16), 6)
def runAI(self):
self.AITime -= 1
if self.AITime < 1:
try:
diff = findClosestPlayer(self.x, self.y)["difference"]
weightsx = [1,1,1]
weightsy = [1,1,1]
randomWeights = randomizeMovement(weightsx, weightsy, diff, 0.15)
weightsx = randomWeights[0]
weightsy = randomWeights[1]
movementx = random.choices([-1, 0, 1], weightsx)[0] * random.randint(1,2)
movementy = random.choices([-1, 0, 1], weightsy)[0] * random.randint(1,2)
self.move(movementx, movementy)
self.AITime = random.randint(150, 200)
except Exception as error:
pass

View File

@ -1,12 +1,14 @@
import pygame
bg_color = pygame.Color('cornsilk4')
bg_color = pygame.Color('lightsalmon3')
bar_color = pygame.Color('white')
red = pygame.Color('brown4')
blue = pygame.Color('cadetblue3')
green = pygame.Color('green3')
grey = pygame.Color("gray26")
black = pygame.Color("black")
white = pygame.Color("white")
purple = pygame.Color("purple")
tile = 34
tileCountx = 50

View File

@ -6,6 +6,20 @@ from player import *
from blocks import *
from enemies import *
def spawnEnemy(type, amount):
for i in range(amount):
for j in range(50):
try:
spot = [random.randint(0, tileCountx - 1), random.randint(0, tileCounty - 1)]
if gameMap[spot[0]][spot[1]]:
raise Exception("spot taken!")
newEnemy = type(uuid.uuid4(), spot[0], spot[1])
gameMap[spot[0]][spot[1]] = newEnemy
enemies[newEnemy.id] = newEnemy
break
except Exception as error:
continue
def generateMap():
gameMap.clear()
for i in range(tileCountx):
@ -21,19 +35,10 @@ def generateMap():
gameMap[spot[0]][spot[1]] = Block(uuid.uuid4(), spot[0], spot[1])
except Exception as error:
continue
for i in range(60):
for j in range(50):
try:
spot = [random.randint(0, tileCountx - 1), random.randint(0, tileCounty - 1)]
if gameMap[spot[0]][spot[1]]:
raise Exception("spot taken!")
newEnemy = Enemy(uuid.uuid4(), spot[0], spot[1])
gameMap[spot[0]][spot[1]] = newEnemy
enemies[newEnemy.id] = newEnemy
break
except Exception as error:
continue
spawnEnemy(Enemy, 20)
spawnEnemy(Smart, 3)
spawnEnemy(Mage, 3)
for id, player in players.items():
maxTries = 5
@ -47,7 +52,7 @@ def generateMap():
gameMap[spot[0]][spot[1]] = player
player.x = spot[0]
player.y = spot[1]
player.pathMap = player.buildOwnPathMap()
player.buildOwnPathMap()
break
except Exception as error:
continue

View File

@ -5,29 +5,34 @@ from globals import *
from blocks import *
def buildPathMap(x, y):
pathMap = []
for i in range(tileCountx):
column = []
for j in range(tileCounty):
column.append(False)
pathMap.append(column)
pathMap[x][y] = (x,y,(0,0))
currentTiles = [pathMap[x][y]]
newTiles = set()
while len(currentTiles) > 0:
for tile in currentTiles:
for i in range(-1,2):
for j in range(-1,2):
newX = tile[0] + i
newY = tile[1] + j
outOfBounds = newX > tileCountx - 1 or newY > tileCounty - 1 or newX < 0 or newY < 0
if (i != 0 or j != 0) and not outOfBounds and not pathMap[newX][newY]:
pathMap[newX][newY] = (newX,newY,(-i,-j))
if not gameMap[newX][newY]:
newTiles.add(pathMap[newX][newY])
currentTiles = list(newTiles)
try:
pathMap = []
for i in range(tileCountx):
column = []
for j in range(tileCounty):
column.append(False)
pathMap.append(column)
pathMap[x][y] = (x,y,(0,0))
currentTiles = [pathMap[x][y]]
newTiles = set()
return pathMap
while True:
for tile in currentTiles:
for i in range(-1,2):
for j in range(-1,2):
newX = tile[0] + i
newY = tile[1] + j
if (i != 0 or j != 0) and not checkOOBounds((newX,newY)) and not pathMap[newX][newY]:
pathMap[newX][newY] = (newX,newY,(-i,-j))
if not gameMap[newX][newY] or hasattr(gameMap[newX][newY], "usesPathMap"):
newTiles.add(pathMap[newX][newY])
if len(currentTiles) < 1:
break
currentTiles = list(newTiles)
newTiles = set()
return pathMap
except Exception as error:
print(error)
raise error
class Player:
def __init__(self, id, x, y, sprite, keys):
@ -41,6 +46,7 @@ class Player:
self.PLAYER = True
self.kills = 0
self.lives = 3
self.alive = True
commands = {
"n": lambda: self.move(0,-1),
@ -68,6 +74,8 @@ class Player:
self.pull = True
else:
self.pull = False
if keys[pygame.K_o]:
print(self.pathMap)
for command in self.commands:
try:
if keys[command[0]]:
@ -87,7 +95,7 @@ class Player:
def move(self, x, y):
try:
if self.x + x > tileCountx - 1 or self.y + y > tileCounty - 1 or self.x + x < 0 or self.y + y < 0:
if checkOOBounds((self.x + x, self.y + y)):
raise Exception("Cannot move off edge!")
pulling = self.pull and hasattr(gameMap[self.x - x][self.y - y], "BLOCK")
if gameMap[self.x + x][self.y + y]:
@ -98,16 +106,16 @@ class Player:
self.x += x
self.y += y
gameMap[self.x][self.y] = self
for id, player in players.items():
try:
player.buildOwnPathMap()
except Exception as error:
print(error)
try:
if pulling:
gameMap[self.x - 2*x][self.y - 2*y].pulled(x, y)
except:
pass
for id, player in players.items():
try:
player.buildOwnPathMap()
except Exception as error:
print(error)
except Exception as error:
raise error
@ -119,6 +127,7 @@ class Player:
for i in range(maxTries + 1):
if self.lives < 1:
del players[self.id]
self.alive = False
break
if i == maxTries:
raise Exception("No spots found for player!")
@ -130,6 +139,10 @@ class Player:
self.x = spot[0]
self.y = spot[1]
self.lives -= 1
try:
self.buildOwnPathMap()
except Exception as error:
print(error)
break
except Exception as error:
continue

2
requirements.txt Normal file
View File

@ -0,0 +1,2 @@
profilehooks==1.12.0
pygame==2.5.2

4
utilities.py Normal file
View File

@ -0,0 +1,4 @@
from globals import *
def checkOOBounds(pos):
return pos[0] > tileCountx - 1 or pos[1] > tileCounty - 1 or pos[0] < 0 or pos[1] < 0