-1

This is my code so far:

from JMSSGraphics import *
import math
import random

class Zombie:
    # attributes:
    # x
    # y
    # infected
    # image

    # we need to define a special function
    # that lets us 'construct' an object from this class
    # this special function is called a constructor

    def __init__(self):
        # creating my attributes
        # and assigning them to initial values
        self.x = 0
        self.y = 0
        self.img = None
        self.speed = 0
        self.rotation = 0
        # Must use self so that variables
        # do not lose values after function returns

class Player:
    def __init__(self):
        self.x = 0
        self.y = 0
        self.img = None
        self.speed = 0
        self.rotation = 0
        self.fireSpeed = 0

class Bullet:
    def __init__(self):
        self.x = 0
        self.y = 0
        self.speed = 0
        self.img = None
        self.rotation = 0
        self.locationVector = []
    def __del__(self):
        pass

class Wall:
    def __init__(self):
        self.x1 = 0
        self.y1 = 0
        self.x2 = 0
        self.y2 = 0

jmss = Graphics(width = 800, height = 600, title = "city", fps = 120)

#Zombie ratio
zombieHeightFactor = 1.205
zombieWidth = 50

zombieHeight = zombieWidth * zombieHeightFactor
#Player ratio
playerHeightFactor = 0.66
playerWidth = 50

playerHeight = playerWidth * playerHeightFactor
#Bullet ratio
bulletHeightFactor = 0.28
bulletWidth = 35

bulletHeight = bulletWidth * bulletHeightFactor

zombiesList = []
n = 0
while n < 7:
    newZombie = Zombie()
    newZombie.img = jmss.loadImage("zombieImage.png")
    newZombie.x = random.randint(10,790)
    newZombie.y = random.randint(10,590)
    newZombie.speed = random.uniform(1,3)
    print(newZombie.speed)
    zombiesList.append(newZombie)
    n+=1

#Creating player object
player = Player()
player.img = jmss.loadImage("PlayerSprite.png")
player.x = 400
player.y = 300
player.speed = 10
player.fireSpeed = 20

bulletList = []

cooldown = 0


@jmss.mainloop
def Game():
    global cooldown
####################PLAYER LOOK###################################
    mouseX = jmss.mouseCoordinate()[0]
    mouseY = jmss.mouseCoordinate()[1]
    if mouseX-player.x > 0:
        angle = 360 - math.degrees(math.atan((mouseY-player.y)/(mouseX-player.x))) #Calculates angle between player and mouse in degrees
        player.rotation = angle
    if mouseX - player.x < 0:
        angle = 360 - math.degrees(math.atan((mouseY-player.y)/(mouseX-player.x))) #Calculates angle between player and mouse in degrees
        player.rotation = angle + 180 

####################PLAYER MOVEMENT#################################
    jmss.clear(1,1,1,1)
    if jmss.isKeyDown(KEY_W):
        player.y += player.speed
    if jmss.isKeyDown(KEY_A):
        player.x -= player.speed
    if jmss.isKeyDown(KEY_D):
        player.x += player.speed
    if jmss.isKeyDown(KEY_S):
        player.y -= player.speed

    if player.x > 800: ##ADDING BORDERS 
        player.x = 800
    if player.x < 0:
        player.x = 0
    if player.y > 600:
        player.y = 600
    if player.y < 0:
        player.y = 0
    jmss.drawImage(player.img,player.x,player.y,width = playerWidth,height = playerHeight,rotation = player.rotation)
####################PLAYER SHOOT####################################
    if jmss.isKeyDown(KEY_SPACE) and cooldown > player.fireSpeed:
        cooldown = 0
        bullet = Bullet()
        bullet.img = jmss.loadImage("bullet.png")
        bullet.x = player.x
        bullet.y = player.y
        bullet.speed = 20
        bullet.locationx = mouseX
        bullet.locationy = mouseY
        bullet.rotation = player.rotation
        bulletList.append(bullet)


    n = 0
    while n < len(bulletList):
        bullet = bulletList[n]

        bullet.locationVector = [math.cos(math.radians(bullet.rotation)),math.sin(math.radians(bullet.rotation))]

        bullet.x += bullet.locationVector[0]*bullet.speed
        bullet.y += -bullet.locationVector[1]*bullet.speed


        jmss.drawImage(bullet.img,bullet.x,bullet.y,width = bulletWidth,height = bulletHeight,rotation = bullet.rotation)
        if bullet.x > 800:
            del bulletList[n]
        elif bullet.y > 600:
            del bulletList[n]


        n += 1
    cooldown += 1

############################ZOMBIE AI#########################################
    n = 0
    while n < len(zombiesList):
        currentZombie = zombiesList[n]

        if player.x-currentZombie.x > 0:
            angle = 360 - math.degrees(math.atan((player.y-currentZombie.y)/(player.x-currentZombie.x))) #Calculates angle between player and mouse in degrees
            currentZombie.rotation = angle
        if player.x - currentZombie.x < 0:
            angle = 360 - math.degrees(math.atan((player.y-currentZombie.y)/(player.x-currentZombie.x))) #Calculates angle between player and mouse in degrees
            currentZombie.rotation = angle + 180

        if currentZombie.x < player.x:
            currentZombie.x += currentZombie.speed
        if currentZombie.x > player.x:
            currentZombie.x -= currentZombie.speed
        if currentZombie.y < player.y:
            currentZombie.y += currentZombie.speed
        if currentZombie.y > player.y:
            currentZombie.y -= currentZombie.speed

        jmss.drawImage(currentZombie.img,currentZombie.x,currentZombie.y,zombieWidth,zombieHeight,currentZombie.rotation)
        currentZombie.speed += 0.001
        n += 1

######################POWER UP################################################
        spawnChance = random.randint(0,10000)

        if spawnChance == 5000:
            print("SPAWN POWERUP")


##########################CREATING ENVIRONMENT###############################

jmss.run()

What I wanted to to was improve the zombie AI so that is was far less boring and predictable. Any help would be appreciated :)

So far what I have done on the AI is just simply adjust the x and y coordinates of the enemy object depending on whether or not they are less or more than that of the player. It only works on a 2 dimensional level with x or y but not both.

  • Luck for your endeavour. Unfortunately SO does not provide Tutorials. Please read [on topic](https://stackoverflow.com/help/on-topic). Your question is too broad for the scope of SO. – Patrick Artner Jul 24 '18 at 13:27
  • Welcome to StackOverflow. Please read and follow the posting guidelines in the help documentation, as suggested when you created this account. [On topic](http://stackoverflow.com/help/on-topic), [how to ask](http://stackoverflow.com/help/how-to-ask), and [... the perfect question](https://codeblog.jonskeet.uk/2010/08/29/writing-the-perfect-question/) apply here. StackOverflow is not a design, coding, research, or tutorial service. – Prune Jul 24 '18 at 15:54

1 Answers1

0

The zombie AI in the OP works as a tracking controller. That means, the Zombie is following the human player. Improving this idea can be done with tracking on a different abstraction level. In the sourcecode, the tracking is only available for euclidean space, that is the difference in 2d coordinates between player and zombie. A more abstract measurement is everything what has to do with natural language. For example, the human player can be in a mode called “aggressive” which is equal to a fast move between two points, and the zombie can react to this mode also with an aggressive behavior. A second opportunity to classify the actions, is to define geometric zones. The human player can be zone A, B or C, and the zombie can have a rule to only attack the player if he is the same zone. This will make his behavior less predictable for a casual gamer.

To create more complex characters a dedicated task model makes sense. An easy way to create such model from scratch is a creativity technique called mind mapping. In the center of a paper the problem is written down, and then the programmers determines possible actions for the AI. The actions are ordered into subactions (called layers). If the mind map grows into a huge network, it is time for implementing the system in executable source code. This can be done manually with a version control system.

Realizing complex Artificial Intelligence systems has always to do with natural language. The idea is not to describe the problem mathematically like diff=pos.x-pos.y but on a linguistic level. The domain of a zombie game has to be described with stories, mindmaps, characters, actions and concept map. This results into a abstract view on the problem. If it is unclear, how the mindmap has to look like, good inspirational sources are other games from the same context, movies and famous writings. Programming the sourcecode itself is story telling on the medium of computergames.

Manuel Rodriguez
  • 734
  • 4
  • 18