Doc: small changes
[galtack.git] / galtack_loadable.py
blob21c0cd8dbbe508fc9912472e9319c558f23d3901
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 """
4 GalTacK runtime-loadable module.
5 """
6 # Copyright (C) 2007 Michael Carter
7 # Copyright (C) 2007 Felix Rabe <public@felixrabe.textdriven.com>
8 # Copyright (C) 2007 Phil Hassey (originator of ld488 code)
10 # WARNING: This code contains bits from the Ludum Dare version of Galcon,
11 # which is licensed under the GNU GPL. Watch out for "ld488" markers.
12 # This file is under the GNU GPL license for now.
14 # This matter has not yet been discussed with Phil Hassey. I, Felix Rabe,
15 # do not want any legal grey area in the code, so the whole project might
16 # change from MIT license to GPL license, or Phil gives his blessing to
17 # include those bits in MIT-licensed code.
19 #### IGNORE THIS PART:
21 # Permission is hereby granted, free of charge, to any person obtaining a
22 # copy of this software and associated documentation files (the
23 # "Software"), to deal in the Software without restriction, including
24 # without limitation the rights to use, copy, modify, merge, publish,
25 # distribute, sublicense, and/or sell copies of the Software, and to permit
26 # persons to whom the Software is furnished to do so, subject to the
27 # following conditions:
29 # The above copyright notice and this permission notice shall be included
30 # in all copies or substantial portions of the Software.
32 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
33 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
34 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
35 # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
36 # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
37 # OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
38 # THE USE OR OTHER DEALINGS IN THE SOFTWARE.
40 #### ... UP TILL HERE
42 # Recommended line length or text width: 75 characters.
44 from galtack_client import *
47 class GaltackUniverseView(DrawingArea):
48 """
49 GalTacK universe canvas.
50 """
52 def __init__(self):
53 super(GaltackUniverseView, self).__init__()
54 self.reset()
55 self.connect("expose-event", self.__cb_expose_event)
56 self.set_size_request(640, 480)
58 def reset(self):
59 self.planet_info_list = []
61 def __cb_expose_event(self, widget, event):
62 x, y, w, h = self.allocation
63 cr = self.window.cairo_create()
65 # background
66 cr.rectangle(0, 0, w, h)
67 cr.set_source_rgba(0.1, 0.0, 0.2, 1)
68 cr.fill()
70 e = cr.font_extents()
71 fascent, fdescent, fheight, fxadvance, fyadvance = e
73 # planets
74 for planet_info in self.planet_info_list:
75 cr.set_source_rgba(1, 1, 1, 1)
76 px, py = planet_info.x, planet_info.y
77 cr.arc(px, py, planet_info.radius, 0, PI2)
78 cr.fill()
80 txt = "%u" % planet_info.num
81 e = cr.text_extents(txt)
82 xbearing, ybearing, width, height, xadvance, yadvance = e
83 cr.move_to(px + 0.5 - xbearing - width / 2,
84 py + 0.5 - fdescent + fheight / 2)
85 cr.set_source_rgba(1, 0, 0, 1)
86 cr.show_text(txt)
88 def redraw(self):
89 if self.window is not None:
90 self.window.invalidate_rect(self.allocation, False)
91 return False
94 class GaltackUniverseWindow(WindowF12RawConsoleMixin):
95 """
96 A Window displaying a view of the GalTacK universe.
97 """
99 def __init__(self):
100 super(GaltackUniverseWindow, self).__init__()
101 self.set_title("Universe Window - GalTacK")
102 self.universe_view = self(GaltackUniverseView())
105 class LoadableController(object):
107 Provide some shortcuts for interactive use.
110 def __init__(self, galtack_client, *a, **kw):
111 self.gc = galtack_client
112 self.uw = GaltackUniverseWindow()
113 self.uv = self.uw.universe_view
115 def __call__(self, *a):
116 self.gc.send_commands(a)
118 @staticmethod
119 def __stabilize_planet_pos(planet_pos_list):
120 FPS = 32 # ld488: cnst.py:11
121 BORDER = 40 # ld488: level.py:27
122 PADDING = 8 # ld488: level.py:28
123 # ld488: level.py:89
124 for n in xrange(0,FPS):
125 top = BORDER
126 left = PADDING
127 right = SW-left*2
128 bottom = SH-top*2
129 for i, (p, x, y) in enumerate(planet_pos_list):
130 rad = p.radius
131 x = min(max(x, left + rad), right - rad)
132 y = min(max(y, top + rad), bottom - rad)
133 planet_pos_list[i] = (p, x, y)
134 self.__planet_flock_loop(planet_pos_list)
136 @staticmethod
137 def __planet_flock_loop(planet_pos_list):
138 import math
139 # ld488: flock.pyp:55
141 # for int n=0; n<PARTS; n++:
142 # part *p = &parts[n]
143 # if p->active and p->loop:
144 # if p->type == TYPE_SHIP:
145 # ship_loop(p)
146 # else:
147 # (p->loop)(p)
149 # Nothing to do here, as "p->loop = 0" in: ld488: flock.pyp:128
151 # for int n=0; n<PARTS; n++:
152 # part *a = &parts[n]
153 for n, (ap, ax, ay) in enumerate(planet_pos_list):
154 # if a->active: ## it's always active!
155 # for int m=n+1; m<PARTS; m++: //n+1 ensures that we dont repeat anything
156 for m, (bp, bx, by) in enumerate(planet_pos_list[n+1:]):
157 # part *b = &parts[m]
158 # if b->active:
159 # float dx,dy
160 # dx = b->x-a->x
161 # dy = b->y-a->y
162 dx = bx - ax
163 dy = by - ay
164 # float r = a->r+b->r
165 r = ap.radius + bp.radius
166 # if ABS(dx) > r or ABS(dy) > r:
167 # continue
168 if abs(dx) > r or abs(dy) > r:
169 continue
171 # float dist = sqrt(dx*dx+dy*dy)
172 dist = math.sqrt(dx*dx + dy*dy)
173 # //if b->r > r:
174 # // r = b->r
175 # if dist < r:
176 if dist < r:
177 # if a->target == b:
178 # a->hit = 1
179 # continue
180 # if b->target == a:
181 # b->hit = 1
182 # continue
184 # no targets
186 if dist == 0:
187 dist = 1
188 dx = 1
189 float w = a->w+b->w
192 float mx = (a->x*a->w+b->x*b->w)/w
193 float my = (a->y*a->w+b->y*b->w)/w
195 a->x = mx-(r*b->w*dx)/(dist*w)
196 a->y = my-(r*b->w*dy)/(dist*w)
198 b->x = mx+(r*a->w*dx)/(dist*w)
199 b->y = my+(r*a->w*dy)/(dist*w)
201 def update(self):
202 if self.gc.u64data is None:
203 planets = []
204 else:
205 planets = self.gc.u64data.planets
206 planet_pos_list = []
207 for p in planets:
208 planet_pos_list.append((p, p.x, p.y))
209 self.__stabilize_planet_pos(planet_pos_list)
210 self.uv.planet_info_list = planets
211 self.uv.redraw()
214 def run_loadable(*a, **kw):
215 return LoadableController(*a, **kw)