Exemple #1
0
    def __init__(self, imageDims, fieldOfView, clippingPlanes, originVector,
                 terrainDims, terrainScale, terrainOffsetVector,
                 terrainSpread):
        # Set instance variables
        self.imageDims = imageDims
        self.fieldOfView = fieldOfView
        self.clippingPlanes = clippingPlanes

        # Create the world axes set to define the coordinate system
        xAxis = Vector(1, 0, 0)
        yAxis = Vector(0, 1, 0)
        zAxis = Vector(0, 0, 1)
        self.axes = [originVector, xAxis, yAxis, zAxis]

        # Create the camera
        self.camera = Camera(self.fieldOfView,\
                            self.clippingPlanes,\
                            self.imageDims,\
                            self.axes)

        # Terrain generation
        self.terrainDims = terrainDims
        self.terrainScale = terrainScale
        self.terrainOffsetVector = terrainOffsetVector
        self.terrainSpread = terrainSpread

        self.terrainGenerator = TerrainGenerator(self.terrainDims,
                                                 self.terrainScale,
                                                 self.terrainSpread)
        self.terrainCache = self.generateTerrainRasterPoints(
            self.terrainOffsetVector, -1.0, 0.0, 0.0)
Exemple #2
0
    def generateEntity(self, positionVector, hitboxRadius):
        # Generate the entity-to-world transformation matrix
        entityAxes = [
            positionVector, self.world.axes[1], self.world.axes[2],
            self.world.axes[3]
        ]
        entityMatrix = Entity.generateEntityToWorldMatrix(entityAxes)

        # Define the hitbox vectors in $Object$ coordinates
        hitboxVectors = [Vector(-hitboxRadius, -hitboxRadius, -hitboxRadius),\
                         Vector(+hitboxRadius, +hitboxRadius, +hitboxRadius)]

        return Entity(entityMatrix, hitboxVectors)
Exemple #3
0
    def launchProjectileFromEnemy(self, enemyEntity, hitboxRadius,
                                  velocityMagnitude, damage):
        # Get the velocity vector required to hit the player from the entity's
        #   position.
        velocityVector = Vector.getVelocityFromPointToPoint(
            enemyEntity.getPosition(), self.playerPosition, velocityMagnitude)

        self.launchProjectile(enemyEntity.getPosition(), velocityVector,
                              hitboxRadius, damage, True)
Exemple #4
0
    def spawnEnemy(self,
                   positionVector,
                   hitboxRadius=5,
                   health=100,
                   projectileStrength=10):
        # Generate the entity-to-world transformation matrix
        enemyAxes = [
            positionVector, self.world.axes[1], self.world.axes[2],
            self.world.axes[3]
        ]
        enemyMatrix = Entity.generateEntityToWorldMatrix(enemyAxes)

        # Define the hitbox vectors in $Object$ coordinates
        hitboxVectors = [Vector(-hitboxRadius, -hitboxRadius, -hitboxRadius),\
                         Vector(+hitboxRadius, +hitboxRadius, +hitboxRadius)]

        self.entities.append(
            Enemy(enemyMatrix, hitboxVectors, health, projectileStrength))
Exemple #5
0
    def __init__(self,
                 entityToWorldMatrix,
                 hitboxVectorList,
                 health,
                 projectileStrength,
                 velocityVector=Vector(0, 0, 0)):
        super().__init__(entityToWorldMatrix, hitboxVectorList, velocityVector)

        self.health = health
        self.projectileStrength = projectileStrength
Exemple #6
0
    def launchProjectile(self,
                         positionVector,
                         velocityVector,
                         hitboxRadius,
                         damage,
                         launchedByEnemy=False):
        # Generate the projectile-to-world transformation matrix
        projectileAxes = [
            positionVector, self.world.axes[1], self.world.axes[2],
            self.world.axes[3]
        ]
        projectileMatrix = Entity.generateEntityToWorldMatrix(projectileAxes)

        # Define the hitbox vectors in $Object$ coordinates
        hitboxVectors = [Vector(-hitboxRadius, -hitboxRadius, -hitboxRadius),\
                         Vector(+hitboxRadius, +hitboxRadius, +hitboxRadius)]

        self.entities.append(
            Projectile(projectileMatrix, hitboxVectors, velocityVector, damage,
                       launchedByEnemy))
Exemple #7
0
    def moveCamera(self, dx, dy, dz):
        origin = self.axes[0]

        self.axes[0] = Vector(origin.x + dx, origin.y + dy, origin.z + dz)

        self.camera = Camera(self.fieldOfView,\
                            self.clippingPlanes,\
                            self.imageDims,\
                            self.axes)

        self.terrainOffsetVector.x += dx
        self.terrainOffsetVector.y += dy
        self.terrainOffsetVector.z += dz

        self.setTerrainCache(self.terrainOffsetVector)
Exemple #8
0
    def generateTerrainVectors(self, terrainOffsetVector, zSign, xShift,
                               zShift):
        perlinGrid = self.generateGrid(xShift, zShift)

        yank = len(perlinGrid)
        yeet = range(len(perlinGrid[0]))

        offsetX = terrainOffsetVector.x
        offsetY = terrainOffsetVector.y
        offsetZ = terrainOffsetVector.z

        return [[
            Vector(self.spread * (x - yank // 2) + offsetX,
                   perlinGrid[x][z] + offsetY,
                   (zSign * (self.spread * z + offsetZ))) for z in yeet
        ] for x in range(len(perlinGrid))]
Exemple #9
0
    def __init__(self, entityToWorldMatrix, hitboxVectorList, velocityVector = Vector(0,0,0)):
        if (len(hitboxVectorList) != 2):
            raise Exception("Invalid hitbox vector list length")

        self.entityToWorldMatrix = entityToWorldMatrix
        self.worldToEntityMatrix = Matrix.inverse( self.entityToWorldMatrix )
        self.hitboxVectorList = hitboxVectorList
        self.velocityVector = velocityVector

        self.cachedWorldHitboxVectors = []
        self.cachedEntityHitboxVertexVectors = []
        self.cachedWorldHitboxVertexVectors = []

        self.regenWorldHitboxVectors = True
        self.regenEntityHitboxVertexVectors = True
        self.regenWorldHitboxVertexVectors = True

        self.visible = True
Exemple #10
0
    def pointVectorMultiply(self, vector):
        outputX = vector.x * self.values[0][0] +\
                    vector.y * self.values[1][0] +\
                    vector.z * self.values[2][0] +\
                    vector.w * self.values[3][0]
        outputY = vector.x * self.values[0][1] +\
                    vector.y * self.values[1][1] +\
                    vector.z * self.values[2][1] +\
                    vector.w * self.values[3][1]
        outputZ = vector.x * self.values[0][2] +\
                    vector.y * self.values[1][2] +\
                    vector.z * self.values[2][2] +\
                    vector.w * self.values[3][2]
        outputW = vector.x * self.values[0][3] +\
                    vector.y * self.values[1][3] +\
                    vector.z * self.values[2][3] +\
                    vector.w * self.values[3][3]

        return Vector(outputX / outputW, outputY / outputW, outputZ / outputW,
                      1)
Exemple #11
0
    def getEntityHitboxVertexVectors(self):
        if (not self.regenEntityHitboxVertexVectors):
            return self.cachedEntityHitboxVertexVectors

        minimumVector = min(self.hitboxVectorList)
        maximumVector = max(self.hitboxVectorList)

        hitboxVertexVectors = []

        (x0, y0, z0) = (minimumVector.x, minimumVector.y, minimumVector.z)
        (x1, y1, z1) = (maximumVector.x, maximumVector.y, maximumVector.z)

        for x in (x0, x1):
            for y in (y0, y1):
                for z in (z0, z1):
                    hitboxVertexVectors.append( Vector(x, y, z) )

        self.cachedEntityHitboxVertexVectors = hitboxVertexVectors
        self.regenEntityHitboxVertexVectors = False

        return hitboxVertexVectors
Exemple #12
0
    def getPosition(self):
        x = self.entityToWorldMatrix.values[3][0]
        y = self.entityToWorldMatrix.values[3][1]
        z = self.entityToWorldMatrix.values[3][2]

        return Vector(x,y,z)
Exemple #13
0
    def gameLoop(self):
        timeStartGameLoop = time.time()

        if "w" in self.keysPressed:
            self.zStep = +self.movementSpeed
        elif "s" in self.keysPressed:
            self.zStep = -self.movementSpeed
        else:
            self.zStep = 0

        if "a" in self.keysPressed:
            self.xStep = +self.movementSpeed
        elif "d" in self.keysPressed:
            self.xStep = -self.movementSpeed
        else:
            self.xStep = 0

        if not self.paused and not self.gameIsOver:
            (nearClip, farClip) = self.clippingPlanes

            # Move terrain
            if (self.xStep != 0 or self.zStep != 0):
                self.shiftTerrain(self.xStep, self.zStep)

                self.updateTerrain = True

            # Launch projectile
            if (self.queueProjectileLaunch
                    and self.playerShootTimer >= self.playerShootTimeout
                    and self.ammoCount > 0):
                self.launchProjectile(self.playerPosition,
                                      Vector(0, 0, -self.projectileSpeed),
                                      self.projectileHitboxRadius,
                                      self.playerProjectileDamage)
                self.ammoCount -= 1
                self.playerShootTimer = 0
            elif self.queueProjectileLaunch:
                self.queueProjectileLaunch = False

            # Spawn another enemy if the timer is done
            if (self.enemySpawnTimer >
                (len(self.entities)**0.4) * self.enemySpawnDelay
                    and len(self.entities) <= self.maxEntityCount):
                self.spawnEnemy(
                    Vector(random.randint(-30, 30), 0,
                           random.randint(-80, -35)))
                self.enemySpawnTimer = 0

            # Ammo regen
            if (self.ammoRegenTimer > self.ammoRegenDelay):
                self.ammoCount += self.ammoRegenAmount
                self.ammoRegenTimer = 0

                self.ammoCount = min(self.initAmmoCount, self.ammoCount)

            # Shield regen
            if (self.shieldRegenTimer > self.shieldRegenDelay
                    and self.shieldPoints > 0):
                self.shieldPoints += self.shieldRegenAmount
                self.shieldRegenTimer = 0

                self.shieldPoints = min(self.initShieldPoints,
                                        self.shieldPoints)

            for entity in self.entities:
                entityVelocity = entity.velocityVector
                entity.translate(entityVelocity.x - self.xStep,
                                 entityVelocity.y,
                                 entityVelocity.z + self.zStep)

                if (abs(entity.entityToWorldMatrix.values[3][2]) >
                        2 * farClip):  # Despawn condition
                    self.entities.remove(entity)
                elif (abs(entity.entityToWorldMatrix.values[3][2] > farClip)
                      ):  # Not visible condition
                    entity.visible = False
                elif not entity.visible:
                    entity.visible = True

                # Shoot on time if an enemy. If projectile, check collisions
                if isinstance(entity, Enemy):
                    if self.enemyShootTimer > self.enemyShootDelay:
                        self.launchProjectileFromEnemy(
                            entity, self.projectileHitboxRadius,
                            self.projectileSpeed, self.enemyProjectileDamage)
                        self.enemyShootTimer = 0
                else:
                    for otherEntity in self.entities:
                        if (entity != otherEntity
                                and not isinstance(otherEntity, Projectile)):
                            if entity.spawnedByEnemy:
                                if entity.collidesWith(
                                        self.playerEntity
                                ) or self.playerEntity.collidesWith(entity):
                                    self.playerHit(entity.strength)

                                    if entity in self.entities:
                                        self.entities.remove(entity)
                            else:
                                if entity.collidesWith(
                                        otherEntity
                                ) or otherEntity.collidesWith(entity):
                                    if (otherEntity in self.entities):
                                        self.entities.remove(otherEntity)

                                    if (entity in self.entities):
                                        self.entities.remove(entity)

                                    self.score += self.scoreIncrement

        # Draw with new information
        self.drawAll(drawTerrain=self.updateTerrain,
                     drawHitboxes=not self.paused and not self.gameIsOver,
                     drawOverlay=True)
        self.updateTerrain = False

        timeEndGameLoop = time.time()

        timeElapsedGameLoop = timeEndGameLoop - timeStartGameLoop

        # This is necessary just in case the game lags. If the game loop takes
        #   longer than the timer delay, then python will pin the CPU usage at
        #   100 unless a small buffer is added.
        if (timeElapsedGameLoop >= self.timerDelay):
            self.updateTimers(timeElapsedGameLoop + self.frameBufferTime)
            self.after(timeElapsedGameLoop + self.frameBufferTime,
                       self.gameLoop)
        else:
            self.updateTimers(self.timerDelay)
            self.after(self.timerDelay, self.gameLoop)
Exemple #14
0
    def __init__(self, width=1080, height=720):
        # Tkinter initialization
        super().__init__()

        if winsoundAvailable:
            winsound.PlaySound(
                "tatchwave.wav",
                winsound.SND_LOOP + winsound.SND_ASYNC | winsound.SND_ALIAS)

        ### User customization

        # User View Variables
        self.fieldOfView = 90
        self.clippingPlanes = (0.1, 100)
        self.originVector = Vector(0, -14, 0)
        self.terrainDims = (54, 29)
        self.terrainScale = 6.4
        self.terrainOffsetVector = Vector(0, 0, 12)
        self.terrainSpread = 1.8

        # User Gameplay Variables
        self.targetFPS = 30
        self.movementSpeed = 1.0
        self.backgroundColor = "black"
        self.terrainColor = "white"
        self.enemyColor = "red"
        self.projectileColor = "green"
        self.playerShootTimeout = 50
        self.enemySpawnDelay = 450
        self.enemyShootDelay = 400
        self.maxEntityCount = 10

        self.ammoRegenDelay = 450
        self.shieldRegenDelay = 1250
        self.ammoRegenAmount = 1
        self.shieldRegenAmount = 5

        self.initAmmoCount = 5
        self.initHealthPoints = 100
        self.initShieldPoints = 60
        self.playerHitboxRadius = 5

        self.projectileHitboxRadius = 0.75
        self.projectileSpeed = 4
        self.playerProjectileDamage = 20
        self.enemyProjectileDamage = 14

        self.scoreIncrement = 100

        ### Game variables

        # Set the instance variables
        self.width = width
        self.height = height

        # Game state
        self.paused = False
        self.gameIsOver = False
        self.keysPressed = set()
        self.score = 0
        self.ammoCount = self.initAmmoCount
        self.healthPoints = self.initHealthPoints
        self.shieldPoints = self.initShieldPoints
        self.updateTerrain = True
        self.queueProjectileLaunch = False

        # Timing
        self.frameBufferTime = 25
        self.timerDelay = 1000 // self.targetFPS
        self.enemySpawnTimer = self.enemySpawnDelay  # Spawn instantly
        self.enemyShootTimer = 0
        self.playerShootTimer = 0
        self.ammoRegenTimer = 0
        self.shieldRegenTimer = 0

        # Drawing, terrain movement, entities
        self.terrainLineIdsList = []
        self.hitboxLineIdsList = []
        self.zStep, self.xStep = 0.0, 0.0
        self.xShift, self.zShift = 0.0, 0.0
        self.entities = []

        # Overlay specifications and state
        self.overlayMargin = 10
        self.overlayPauseSize = min(self.width // 20, self.height // 20)
        self.overlayPauseSizeSelectionModifier = 1.4
        self.overlayPauseSelected = False

        ### Operations

        # Create the frame, set window pos, set background color, set resizeable
        self.tatchFrame = TatchFrame(self, self.width, self.height)
        self.geometry(str(self.width) + "x" + str(self.height) + "+0+0")
        self.tatchFrame.tatchCanvas.config(background=self.backgroundColor)
        self.resizable(False, False)

        # Create the necessary game objects
        self.world = World((self.width, self.height), self.fieldOfView,
                           self.clippingPlanes, self.originVector,
                           self.terrainDims, self.terrainScale,
                           self.terrainOffsetVector, self.terrainSpread)
        self.overlay = Overlay(self.width, self.height,
                               self.tatchFrame.tatchCanvas, self.overlayMargin,
                               self.overlayPauseSize,
                               self.overlayPauseSizeSelectionModifier,
                               self.initHealthPoints, self.initShieldPoints,
                               self.initAmmoCount)

        # Bind keyPress/mouse events to their respective functions
        self.bind("<KeyPress>", self.keyDown)
        self.bind("<KeyRelease>", self.keyUp)
        self.bind("<Motion>", self.mouseMoved)
        self.bind("<Button>", self.mousePressed)

        # Bind window events
        self.protocol("WM_DELETE_WINDOW", self.closeWindow)

        # Create the player entity and spawn the first entity
        self.playerPosition = Vector(self.originVector.x,
                                     self.originVector.y / 4,
                                     self.originVector.z)
        self.playerEntity = self.generateEntity(self.playerPosition,
                                                self.playerHitboxRadius)