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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
import os
import pygame
from random import randrange
from display import Scaling, INTERNAL_WIDTH, INTERNAL_HEIGHT
from stats import Stats
DEBUG = os.getenv("DEBUG")
class FieldSprite(pygame.sprite.Sprite):
def __init__(self, area: tuple):
super().__init__()
self.color = (0,255,0,255)
self.dead = False
self.area = area
self.rect = Scaling.area_to_rect(self.area)
self.image = pygame.Surface(self.rect.size)
self.image.fill(self.color)
class SliceSprite(FieldSprite):
def __init__(self, area: tuple ):
super().__init__(area)
self.color = (255,255,255,255)
self.image.fill(self.color)
self.timeout = 300
self.dead = True
def update(self, dt = 0):
if dt:
self.timeout -= dt
self.color = (
(randrange(0,300) < self.timeout) * 255,
(randrange(0,300) < self.timeout) * 255,
(randrange(0,300) < self.timeout) * 255,
255)
if self.timeout <= 0:
self.kill()
else:
self.image.fill(self.color)
class ExplodedField(FieldSprite):
def __init__(self, area: tuple):
super().__init__(area)
self.dead = True
self.color = (255,255,255,255)
self.image.fill(self.color)
self.direction = (
Scaling.factor * (500 - randrange(1000)),
Scaling.factor * (500 - randrange(1000)))
def update(self, dt = 0, **kwargs):
if dt:
self.rect = pygame.Rect(
self.rect.x + self.direction[0] * dt,
self.rect.y + self.direction[1] * dt,
self.rect.w,
self.rect.h)
self.direction = (
self.direction[0] * 0.95,
self.direction[1] * 0.95 + 0.3)
if (self.rect.x > Scaling.resolution[0]
or self.rect.y > Scaling.resolution[1]):
self.kill()
class Field(pygame.sprite.LayeredUpdates):
initial_area = (320_000, 220_000)
def __init__(self):
super().__init__()
self.add(FieldSprite( (0, 0, *__class__.initial_area) ))
self.area_full = __class__.initial_area[0] * __class__.initial_area[1]
def calculate_current_area(self):
return sum( s.area[2]*s.area[3] for s in self.active_sprites() )
def update_stats(self):
""" calculates remaining area and remaining percentage """
Stats.percent = 100 * self.calculate_current_area() / self.area_full
if DEBUG:
print(f"FIELD: {Stats.percent}")
def slice(
self,
pos: tuple,
direction: bool,
thickness: int) -> pygame.Rect:
""" Slice one area into two areas """
# Slicing hits the area?
for overlap in self.get_sprites_at(Scaling.scale_to_display(pos)):
if not overlap.dead:
break
else:
return None
# Save the area information and remove the sprite
ax, ay, aw, ah = overlap.area
overlap.remove(self)
# create new areas if there is any space
if direction:
x1 = ax
x2 = pos[0] - thickness
x3 = pos[0] + thickness
x4 = ax + aw
if x2 > x1:
self.add(FieldSprite( (x1, ay, x2-x1, ah) ))
if x4 > x3:
self.add(FieldSprite( (x3, ay, x4-x3, ah) ))
area = x2, ay, x3-x2, ah
else:
y1 = ay
y2 = pos[1] - thickness
y3 = pos[1] + thickness
y4 = ay + ah
if y2 > y1:
self.add(FieldSprite( (ax, y1, aw, y2-y1) ))
if y4 > y3:
self.add(FieldSprite( (ax, y3, aw, y4-y3) ))
area = ax, y2, aw, y3-y2
self.explode(area)
self.add(SliceSprite(area))
return Scaling.area_to_rect( area )
def active_sprites(self):
""" Returns all sprites that are not dead """
return [s for s in self.sprites() if not s.dead]
def explode(self, area):
sx, sy, w, h = area
for x in range(int(sx),int(sx+w),4_000):
for y in range(int(sy),int(sy+h),3_000):
self.add(ExplodedField((x,y,3_000,3_000)))
def kill_if_not_colliding(self, sprites):
""" If there is empty fields that are not yet dead kill them """
for field in self.active_sprites():
for enemy in sprites:
if enemy.rect.colliderect(field.rect):
break
else:
self.explode(field.area)
field.remove(self)
|