-
Notifications
You must be signed in to change notification settings - Fork 1
/
projectile.py
97 lines (89 loc) · 3.87 KB
/
projectile.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import math
import random
import pygame.draw
from constants import *
from image_manager import ImageManager
from particle import Spatter
from sound_manager import SoundManager
class Projectile:
def __init__(self, frame, x, y, angle, r=10, v=BULLET_SPEED, damage=1):
self.frame = frame
self.x = x
self.y = y
self.r = r
self.vx = math.cos(angle) * v
self.vy = math.sin(angle) * v
self.damage = damage
self.zombies_hit = set()
self.hit = False
self.explode_time = 0.05
SoundManager.load(f"assets/audio/terrain_shot_impact_1.ogg")
SoundManager.load(f"assets/audio/terrain_shot_impact_2.ogg")
SoundManager.load(f"assets/audio/terrain_shot_impact_3.ogg")
SoundManager.load(f"assets/audio/terrain_shot_impact_4.ogg")
for i in range(13):
SoundManager.load(f"assets/audio/ZR_shot_impact_{i+1}.ogg")
self.sprite = ImageManager.load("assets/images/one_bullet.png")
def update(self, dt, events):
if self.hit:
self.explode_time -= dt
if self.explode_time <= 0:
self.frame.projectiles.remove(self)
return
# Move
self.x += self.vx * dt
self.y += self.vy * dt
# Check for wall collision
tiles = self.frame.grid.get_nearby_tile_rects((self.x, self.y), self.r, self.r)
for tile in tiles:
d = self.collide(tile)
if d:
self.hit = True
i = random.randint(1, 4)
SoundManager.load(f"assets/audio/terrain_shot_impact_{i}.ogg").play()
break
# Check for zombie collision
for zombie in self.frame.zombies:
if zombie in self.zombies_hit:
continue
if self.collide_zombie(zombie):
knock = self.frame.game.upgrade_levels[KNOCK]*2 + 1
zombie.vx += self.vx * BULLET_FORCE * knock
if zombie.ballistic:
zombie.vy += self.vy * BULLET_FORCE * knock
vmag = math.sqrt(self.vx**2 + self.vy**2)
vnorm = self.vx/vmag, self.vy/vmag
self.frame.particles.append(Spatter((zombie.x + vnorm[0]*zombie.r, zombie.y + vnorm[1]*zombie.r), math.degrees(math.atan2(-vnorm[1], vnorm[0]))))
zombie.hit(self.damage)
self.zombies_hit.add(zombie)
if len(self.zombies_hit) >= self.frame.game.upgrade_levels[PIERCE] + 1:
self.hit = True
i = random.randint(1, 13)
SoundManager.load(f"assets/audio/ZR_shot_impact_{i}.ogg").play()
break
def draw(self, surface, offset):
if self.hit:
pygame.draw.circle(surface, (255, 255, 180), (self.x + offset[0], self.y + offset[1]), self.r * 2)
else:
surf = self.sprite
angle = math.atan2(-self.vy, self.vx) + math.pi
angle = math.degrees(angle)
surf = pygame.transform.rotate(surf, angle)
x = self.x - surf.get_width()//2 + offset[0]
y = self.y - surf.get_height()//2 + offset[1]
surface.blit(surf, (x, y))
#pygame.draw.circle(surface, (50, 50, 50), (self.x + offset[0], self.y + offset[1]), self.r)
def collide(self, rect):
""" Return true if collision occurs, else False """
px = max(rect.left, min(rect.right, self.x))
py = max(rect.top, min(rect.bottom, self.y))
d = math.sqrt((px - self.x) ** 2 + (py - self.y) ** 2)
return d <= self.r
def collide_zombie(self, zombie):
dx = zombie.x - self.x
dy = zombie.y - self.y
if zombie.ballistic:
return math.sqrt(dx ** 2 + dy ** 2) < zombie.r + self.r
else:
rx, ry = zombie.get_tile_range()
return abs(dx) - rx - self.r < 0 and abs(dy) - rx - self.r < 0