File: storms.py

package info (click to toggle)
lightyears 1.5.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 25,804 kB
  • sloc: python: 5,532; sh: 39; makefile: 6
file content (154 lines) | stat: -rw-r--r-- 4,718 bytes parent folder | download | duplicates (2)
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
154
#
# 20,000 Light Years Into Space
# This game is licensed under GPL v2, and copyright (C) Jack Whitham 2006-07.
#

import math , pygame


from . import partial_vector, particle, sound, quakes
from .quiet_season import Quiet_Season
from .primitives import *
from .game_types import *
from . import network
from .grid import Float_Grid_To_Scr


storm_sound: Optional[sound.Persisting_Sound] = None
storm_graphics: Optional[List[SurfaceType]] = None

class Storm_Season(Quiet_Season):
    def __init__(self, net: network.Network,
                 storm_difficulty: float) -> None:
        Quiet_Season.__init__(self, net)
        self.name = "Storm"
        self.storms: List[Storm] = []
        self.storm_difficulty = storm_difficulty

        global storm_graphics
        assert ( storm_graphics is not None )

    def Get_Period(self) -> int:
        return 20

    def Per_Period(self) -> None:
        self.storms.append(Storm(self.net, self.storm_difficulty))
        removal: List[int] = []
        for (i, s) in enumerate(self.storms):
            if ( s.Is_Offscreen() ):
                removal.insert(0, i)
        for i in removal:
            self.storms.pop(i)

    def Draw(self, output: SurfaceType, update_area: UpdateAreaMethod) -> None:
        for s in self.storms:
            s.Draw(output, update_area)

    def Get_Extra_Info(self) -> List[StatTuple]:
        return [] #[ ((255,0,0), 16, "Storms are coming!" )]

    def Per_Frame(self, frame_time: float) -> None:
        for s in self.storms:
            s.Think(frame_time)


class Storm:
    def __init__(self, net: network.Network, difficulty: float) -> None:
        self.net = net
        self.difficulty = difficulty
        self.storm_frame = 0

        [a, b] = quakes.Make_Quake_SF_Points(self.net.demo, 5)
        if ( self.net.demo.randint(0,1) == 0 ):
            (a, b) = (b, a) # flip - ensures start point is not always on top or left

        self.pos: FloatSurfacePosition
        (self.pos, dest) = (a, b)

        (sx,sy) = self.pos
        (tx,ty) = dest
        dx = tx - sx
        dy = ty - sy

        speed = (( self.net.demo.random() * 1.5 ) + 0.6 ) * self.difficulty

        # Convert the overall displacement vector (dx,dy) into a velocity.
        distance = self.net.demo.hypot(dx,dy)
        self.velocity = partial_vector.Partial_Vector((0, 0), (dx, dy), (speed, distance))

        # How long does this storm live?
        self.countdown = distance / speed


    def Draw(self, output: SurfaceType, update_area: UpdateAreaMethod) -> None:
        global storm_graphics
        assert storm_graphics is not None
        sfx = storm_graphics[ self.storm_frame ]

        r = sfx.get_rect()
        (x, y) = Float_Grid_To_Scr(self.pos)
        r.centerx = int(x)
        r.centery = int(y)
        (x, y) = r.topleft
        x = int(x)
        y = int(y)
        r.topleft = (x,y)
        #pygame.draw.rect(output, (255,255,255), r, 1)
        output.blit(sfx, r.topleft)
        update_area(r)

    def Think(self, frame_time: float) -> None:
        # Do damage to things within the storm
        (cx,cy) = self.pos
        cx = int(cx)
        cy = int(cy)

        dmg = STORM_DAMAGE * self.difficulty

        for x in range(cx - 1, cx + 2):
            for y in range(cy - 1, cy + 2):
                key = (x,y)

                global storm_sound
                assert storm_sound is not None

    
                for pipe in self.net.storm_pipe_grid.Get_Pipes(key):
                    if (( not pipe.Is_Destroyed() )
                    and ( pipe.Take_Damage(dmg) )):
                        self.net.Destroy(pipe, "storms")
                        storm_sound.Set(1.0)

                if ( self.net.ground_grid.get(key, None) ):
                    node = self.net.ground_grid[ key ]

                    if (( not node.Is_Destroyed() )
                    and ( node.Take_Damage(dmg) )):
                        self.net.Destroy(node, "storms")
                        storm_sound.Set(1.0)

        # Move
        (px,py) = self.pos
        (dx,dy) = self.velocity
        dx *= frame_time
        dy *= frame_time
        self.pos = (px + dx, py + dy)

        global storm_graphics
        assert storm_graphics is not None
        self.storm_frame = ( self.storm_frame + 1 ) % len(storm_graphics)

        self.countdown -= frame_time

    def Is_Offscreen(self) -> bool:
        return ( self.countdown < 0 )


def Set_Screen_Height(height: int) -> None:
    global storm_graphics
    storm_graphics = particle.Make_Particle_Effect(particle.Storm_Particle)

    global storm_sound
    if storm_sound is None:
        storm_sound = sound.Persisting_Sound(Sounds.stormdmg, Sounds.stormbeeps)