Browse code
timing tweaks and gui changes (scrolling map, picking up objects and reworking movement)
edwlan authored on 01/08/2013 05:59:44
Showing 7 changed files
Showing 7 changed files
... | ... |
@@ -5,6 +5,9 @@ from .combat_parts import equipment |
5 | 5 |
from .combat_parts import skills |
6 | 6 |
from .combat_parts import constants as const |
7 | 7 |
|
8 |
+from src import events |
|
9 |
+eh = events.EventHandler() |
|
10 |
+ |
|
8 | 11 |
import collections |
9 | 12 |
import random |
10 | 13 |
|
... | ... |
@@ -48,6 +51,10 @@ class Adventurer(object): |
48 | 51 |
if val > const.KNOCKOUT: val = const.KNOCKOUT |
49 | 52 |
self.attributes.state = val |
50 | 53 |
|
54 |
+ @property |
|
55 |
+ def readable_state(self): |
|
56 |
+ return ['healthy', 'wounded', 'knocked out'][self.state if self.state < 3 else 2] |
|
57 |
+ |
|
51 | 58 |
@classmethod |
52 | 59 |
def randomize(cls, stat_sum=28): |
53 | 60 |
name = '%s %s%s' % ( |
... | ... |
@@ -89,7 +96,9 @@ class Adventurer(object): |
89 | 96 |
if pass_: |
90 | 97 |
if self.weapon is not None: |
91 | 98 |
damage += self.weapon.damage_mod |
92 |
- print '%s inflicts %d damage upon %s' % (self.name, damage, opponent.name) |
|
99 |
+ eh.trigger_event('msg', |
|
100 |
+ '%s inflicts %d damage upon %s' % (self.name, damage, opponent.name) |
|
101 |
+ ) |
|
93 | 102 |
opponent.take_damage(damage) |
94 | 103 |
|
95 | 104 |
def take_damage(self, damage): |
... | ... |
@@ -104,7 +113,9 @@ class Adventurer(object): |
104 | 113 |
if not result: |
105 | 114 |
if damage > 0: |
106 | 115 |
self.state += 1 |
107 |
- print '%s takes %d damage and is now %s' % (self.name, damage, ['healthy', 'wounded', 'ko'][self.state if self.state < 3 else 2]) |
|
116 |
+ eh.trigger_event('msg', |
|
117 |
+ '%s takes %d damage and is now %s' % (self.name, damage, self.readable_state) |
|
118 |
+ ) |
|
108 | 119 |
if self.state >= const.KNOCKOUT: |
109 | 120 |
self.die() |
110 | 121 |
|
... | ... |
@@ -1,3 +1,4 @@ |
1 |
+from src import events |
|
1 | 2 |
import abc |
2 | 3 |
import collections |
3 | 4 |
from . import combat |
... | ... |
@@ -13,6 +14,7 @@ class Overlay(object): |
13 | 14 |
def pos(self): |
14 | 15 |
return self.x, self.y |
15 | 16 |
def __init__(self, x,y, map): |
17 |
+ print self.handled_events |
|
16 | 18 |
self.events = collections.OrderedDict() |
17 | 19 |
self.x = x |
18 | 20 |
self.y = y |
... | ... |
@@ -38,21 +40,30 @@ class Overlay(object): |
38 | 40 |
result = result is None or result # if the event returns a false value besides None, break |
39 | 41 |
if result == False: break |
40 | 42 |
|
41 |
- handled_events = collections.OrderedDict() |
|
42 |
- @classmethod |
|
43 |
- def handle_event(cls, event): |
|
44 |
- def _inner(cb): |
|
45 |
- cls.handled_events.setdefault(event, []).append(cb) |
|
46 |
- return cb |
|
43 |
+ @staticmethod |
|
44 |
+ def add_event(event, cb_name): |
|
45 |
+ def _inner(cls): |
|
46 |
+ if not hasattr(cls, 'handled_events'): |
|
47 |
+ cls.handled_events = {} |
|
48 |
+ for base in cls.bases: |
|
49 |
+ if hasattr(base, 'handled_events'): |
|
50 |
+ cls.handled_events.update(base.handled_events) |
|
51 |
+ cls.handled_events.setdefault(event, []).append(getattr(cls, cb_name)) |
|
52 |
+ return cls |
|
47 | 53 |
return _inner |
48 | 54 |
|
55 |
+ def tick(self): |
|
56 |
+ pass |
|
49 | 57 |
|
50 | 58 |
|
59 |
+@Overlay.add_event('attacked', 'attacked_by') |
|
60 |
+@Overlay.add_event('bumped', 'bumped_by') |
|
51 | 61 |
class Actor(Overlay): |
52 | 62 |
char = ord('@') |
53 | 63 |
color = (255,0,0) |
54 | 64 |
blocks = True |
55 | 65 |
|
66 |
+ handled_events = collections.OrderedDict() |
|
56 | 67 |
@property |
57 | 68 |
def pos(self): |
58 | 69 |
return self.x, self.y |
... | ... |
@@ -63,18 +74,35 @@ class Actor(Overlay): |
63 | 74 |
if adventurer is None: |
64 | 75 |
adventurer = combat.Adventurer.randomize() |
65 | 76 |
self.adventurer = adventurer |
77 |
+ self.repeated_actions = {} |
|
66 | 78 |
|
67 |
- def move(self, dx, dy): |
|
68 |
- dx, dy = self.map.move(self, dx,dy) |
|
79 |
+ def add_repeated_action(self, time, action, *args, **kw): |
|
80 |
+ print 'adding action', action, args, kw |
|
81 |
+ self.repeated_actions.setdefault(time, []).append( (action, args, kw) ) |
|
82 |
+ |
|
83 |
+ def update_pos(self, dx,dy): |
|
69 | 84 |
self.x += dx |
70 | 85 |
self.y += dy |
71 | 86 |
|
87 |
+ def move(self, dx, dy): |
|
88 |
+ print 'moving' |
|
89 |
+ self.map.move(self, dx,dy, self.update_pos) |
|
90 |
+ |
|
72 | 91 |
def tick(self): |
73 | 92 |
result = True |
74 | 93 |
if self.adventurer.state >= 2: |
75 | 94 |
result = False |
76 | 95 |
self.char = ord('%') |
77 | 96 |
self.blocks = False |
97 |
+ else: |
|
98 |
+ ractions = {} |
|
99 |
+ for nleft, actions in self.repeated_actions.items(): |
|
100 |
+ for (action,args,kwargs) in actions: |
|
101 |
+ print action,args,kwargs |
|
102 |
+ action(*args, **kwargs) |
|
103 |
+ if nleft > 1: |
|
104 |
+ ractions.setdefault(nleft-1, []).append( (action,args,kwargs) ) |
|
105 |
+ self.repeated_actions = ractions |
|
78 | 106 |
return result |
79 | 107 |
|
80 | 108 |
def ishostile(self, other): |
... | ... |
@@ -85,32 +113,43 @@ class Actor(Overlay): |
85 | 113 |
if isinstance(other, Actor) and other.ishostile(self): |
86 | 114 |
self.adventurer.attack(other.adventurer) |
87 | 115 |
other.trigger_event('attacked', self) |
88 |
- elif isinstance(other, Object): |
|
116 |
+ |
|
117 |
+ def interact(self, other): |
|
118 |
+ result = False |
|
119 |
+ if isinstance(other, Object): |
|
120 |
+ result = True |
|
89 | 121 |
self.pickup(other) |
90 | 122 |
other.trigger_event('picked_up', self) |
91 | 123 |
|
92 | 124 |
other.trigger_event('bumped', self) |
125 |
+ return result |
|
126 |
+ |
|
127 |
+ def pickup(self, other): |
|
128 |
+ self.inventory.append(other) |
|
93 | 129 |
|
94 |
- @Overlay.handle_event('attacked') |
|
95 | 130 |
def attacked_by(self, other): |
96 | 131 |
if self.adventurer.skills.check('agility'): |
97 | 132 |
self.adventurer.attack(other.adventurer) |
98 | 133 |
|
99 |
- @Overlay.handle_event('bumped') |
|
100 | 134 |
def bumped_by(self, other): |
101 | 135 |
print '%s was bumped by %s' % (type(self).__name__, type(other).__name__) |
102 | 136 |
|
137 |
+@Overlay.add_event('picked_up', 'picked_up_by') |
|
138 |
+@Overlay.add_event('bumped', 'bumped_by') |
|
103 | 139 |
class Object(Overlay): |
104 | 140 |
item = None |
105 |
- @Overlay.handle_event('picked_up') |
|
141 |
+ handled_events = collections.OrderedDict() |
|
106 | 142 |
def picked_up_by(self, other): |
143 |
+ events.EventHandler().trigger_event('msg', 'picked up a %s' % self) |
|
107 | 144 |
self.map.remove(self) |
145 |
+ def bumped_by(self, other): pass |
|
108 | 146 |
|
109 | 147 |
class Weapon(Object): |
110 | 148 |
item = None |
111 | 149 |
|
112 | 150 |
class Potion(Object): |
113 | 151 |
char = ord('!') |
152 |
+ def __str__(self): return 'potion' |
|
114 | 153 |
|
115 | 154 |
class Scroll(Object): |
116 | 155 |
char = ord('!') |
... | ... |
@@ -1,3 +1,6 @@ |
1 |
+if __name__ == '__main__': |
|
2 |
+ execfile('/home/edwlan/python_envs/roguelike/bin/activate_this.py', dict(__file__='/home/edwlan/python_envs/roguelike/bin/activate_this.py')) |
|
3 |
+ |
|
1 | 4 |
import libs.patch_random |
2 | 5 |
import random |
3 | 6 |
#random.seed(2) |
... | ... |
@@ -5,6 +8,7 @@ import random |
5 | 8 |
import libtcodpy as tc |
6 | 9 |
import numpy as np |
7 | 10 |
|
11 |
+from gui import text_display |
|
8 | 12 |
from libs import overlay |
9 | 13 |
from libs import combat |
10 | 14 |
from src import events |
... | ... |
@@ -15,20 +19,32 @@ from src import map |
15 | 19 |
import random |
16 | 20 |
import bisect |
17 | 21 |
|
22 |
+from twisted.internet import reactor |
|
23 |
+import twisted.internet |
|
18 | 24 |
|
19 |
-WIDTH = 79 |
|
20 |
-HEIGHT = 46 |
|
25 |
+ |
|
26 |
+WIDTH = 118 |
|
27 |
+HEIGHT = 62 |
|
21 | 28 |
class Application(object): |
22 | 29 |
def __init__(self): |
23 |
- self.screen = console.Screen(WIDTH, HEIGHT) |
|
30 |
+ self.screen = console.Screen(WIDTH, HEIGHT+5) |
|
31 |
+ self.console = console.Console(WIDTH, HEIGHT, self.screen) |
|
32 |
+ self.message_console = console.Console(WIDTH, 5, self.screen, (0,HEIGHT)) |
|
33 |
+ self.messages = text_display.MessageBox(self.message_console, 5, (10,0), 'msg') |
|
34 |
+ self.fps_display = text_display.Label(self.message_console, (0,0), None) |
|
35 |
+ |
|
24 | 36 |
self.terrain_registry = map.TerrainRegistry() |
25 | 37 |
self.terrain_registry.load_from_file('data/terrain.yml') |
26 |
- self.map = map.Map(WIDTH,HEIGHT, self.terrain_registry) |
|
27 |
- self.player = player.Player(4,5, self.map, combat.Adventurer.randomize()) |
|
38 |
+ self.map = map.Map(200,200, self.terrain_registry) |
|
39 |
+ self.tc_events = events.TCODEventHandler() |
|
28 | 40 |
self.events = events.EventHandler() |
29 |
- player.ArrowHandler(self.player, self.events) |
|
30 | 41 |
|
31 |
- self.actors = [] |
|
42 |
+ self.player = player.Player(4,5, self.map, combat.Adventurer.randomize()) |
|
43 |
+ self.player_stat = text_display.TextBox(self.message_console, 4, (0,1)) |
|
44 |
+ self.player.claim_display(self.player_stat) |
|
45 |
+ player.ArrowHandler(self.player, self.tc_events) |
|
46 |
+ |
|
47 |
+ self.actors = [self.player] |
|
32 | 48 |
for x in range(40): |
33 | 49 |
self.actors.append(overlay.Actor(random.randrange(WIDTH), random.randrange(HEIGHT), self.map)) |
34 | 50 |
|
... | ... |
@@ -36,7 +52,7 @@ class Application(object): |
36 | 52 |
for x in range(50): |
37 | 53 |
self.objects.append(overlay.Potion(random.randrange(WIDTH), random.randrange(HEIGHT), self.map)) |
38 | 54 |
|
39 |
- tc.sys_set_fps(60) |
|
55 |
+ tc.sys_set_fps(30) |
|
40 | 56 |
|
41 | 57 |
def update_actors(self): |
42 | 58 |
to_pop = [] |
... | ... |
@@ -44,25 +60,33 @@ class Application(object): |
44 | 60 |
if not actor.tick(): |
45 | 61 |
bisect.insort(to_pop, idx) |
46 | 62 |
for pop in reversed(to_pop): |
47 |
- self.actors.pop(pop) |
|
63 |
+ actor = self.actors.pop(pop) |
|
64 |
+ self.objects.append(actor) |
|
48 | 65 |
|
49 | 66 |
def init(self): |
50 | 67 |
self.screen.init("test") |
51 |
- self.player.draw() |
|
68 |
+ self.message_console.fill(0,0,128) |
|
69 |
+ #self.player.draw() |
|
52 | 70 |
self.update_actors() |
53 | 71 |
for overlay in self.actors + self.objects: |
54 | 72 |
overlay.draw() |
55 | 73 |
|
56 |
- def run(self): |
|
57 |
- while not tc.console_is_window_closed(): |
|
58 |
- self.events.tick() |
|
59 |
- self.update_actors() |
|
60 |
- self.map.draw(self.screen) |
|
61 |
- tc.console_print(0, 0,1, '%d' % tc.sys_get_fps()) |
|
62 |
- tc.console_flush() |
|
74 |
+ def tick(self): |
|
75 |
+ self.tc_events.tick() |
|
76 |
+ self.fps_display.set_text('%d', tc.sys_get_fps()) |
|
77 |
+ self.update_actors() |
|
78 |
+ self.map.draw(self.console) |
|
79 |
+ self.console.blit() |
|
80 |
+ self.message_console.blit() |
|
81 |
+ tc.console_flush() |
|
82 |
+ if tc.console_is_window_closed(): |
|
83 |
+ reactor.stop() |
|
84 |
+ else: |
|
85 |
+ reactor.callLater(0, self.tick) |
|
63 | 86 |
|
64 | 87 |
|
65 | 88 |
if __name__ == '__main__': |
66 | 89 |
app = Application() |
67 | 90 |
app.init() |
68 |
- app.run() |
|
91 |
+ reactor.callWhenRunning(app.tick) |
|
92 |
+ reactor.run() |
... | ... |
@@ -1,14 +1,55 @@ |
1 | 1 |
import libtcodpy as tc |
2 |
+import numpy as np |
|
2 | 3 |
|
3 | 4 |
class Console(object): |
4 | 5 |
# TBI: must have a self.con member with the console to be drawn on |
5 |
- pass |
|
6 |
+ @property |
|
7 |
+ def dim(self): |
|
8 |
+ return self.width, self.height |
|
6 | 9 |
|
7 |
-class Screen(object): |
|
8 |
- def __init__(self, w, h): |
|
10 |
+ def __init__(self, w,h, parent=None, offset=(0,0)): |
|
9 | 11 |
self.width = w |
10 | 12 |
self.height = h |
11 |
- self.con = 0 |
|
13 |
+ self.offset = offset |
|
14 |
+ self.parent = parent |
|
15 |
+ |
|
16 |
+ if parent is None: |
|
17 |
+ self.con = 0 |
|
18 |
+ else: |
|
19 |
+ self.con = tc.console_new(w,h) |
|
20 |
+ |
|
21 |
+ def blit(self): |
|
22 |
+ if self.parent is not None: |
|
23 |
+ xdst,ydst = self.offset |
|
24 |
+ tc.console_blit(self.con, 0,0, self.width, self.height, self.parent.con, xdst,ydst) |
|
25 |
+ |
|
26 |
+ def set_bg(self, r,g,b): |
|
27 |
+ tc.console_set_default_background(self.con, r,g,b) |
|
28 |
+ |
|
29 |
+ def set_fg(self, r,g,b): |
|
30 |
+ tc.console_set_default_foreground(self.con, r,g,b) |
|
31 |
+ |
|
32 |
+ def clear(self): |
|
33 |
+ tc.console_clear(self.con) |
|
34 |
+ |
|
35 |
+ def fill(self, r,g,b): |
|
36 |
+ r = np.ones(self.dim) * r |
|
37 |
+ g = np.ones(self.dim) * g |
|
38 |
+ b = np.ones(self.dim) * b |
|
39 |
+ tc.console_fill_background(self.con, r,g,b) |
|
40 |
+ |
|
41 |
+ def print_(self, pos, msg, *fmt): |
|
42 |
+ x,y = pos |
|
43 |
+ tc.console_print(self.con, x,y, msg % fmt) |
|
44 |
+ |
|
45 |
+ |
|
46 |
+ |
|
47 |
+ |
|
48 |
+class Screen(Console): |
|
49 |
+ # Root console |
|
12 | 50 |
def init(self, title, fullscreen=False): |
13 | 51 |
tc.console_init_root(self.width, self.height, title, fullscreen, 2) |
14 | 52 |
return self |
53 |
+ |
|
54 |
+ def flush(self): |
|
55 |
+ tc.console_flush() |
... | ... |
@@ -1,6 +1,22 @@ |
1 | 1 |
import libtcodpy as tc |
2 |
+import collections |
|
2 | 3 |
|
3 | 4 |
class EventHandler(object): |
5 |
+ events = {} |
|
6 |
+ def register_event(self, event): |
|
7 |
+ return self.events.setdefault(event, []) |
|
8 |
+ def handle_event(self, event, cb, *a, **kw): |
|
9 |
+ cbs = self.register_event(event) |
|
10 |
+ cbs.append( (cb, a, kw) ) |
|
11 |
+ def trigger_event(self, event, *a, **kw): |
|
12 |
+ for cb, args, kwargs in self.events.get(event,[]): |
|
13 |
+ kw.update(kwargs) |
|
14 |
+ a += args |
|
15 |
+ result = cb(*a, **kw) |
|
16 |
+ if result is not None and not result: break |
|
17 |
+ |
|
18 |
+ |
|
19 |
+class TCODEventHandler(object): |
|
4 | 20 |
def __init__(self): |
5 | 21 |
self.key = tc.Key() |
6 | 22 |
self.mouse = tc.Mouse() |
... | ... |
@@ -51,35 +51,47 @@ class Map(object): |
51 | 51 |
for other in self.overlays[x,y]: |
52 | 52 |
object.bump(other) |
53 | 53 |
|
54 |
- def move(self, object, dx,dy): |
|
55 |
- self.overlays[object.pos].remove(object) |
|
54 |
+ def interact(self, a, bs): |
|
55 |
+ print 'interacting with:', bs |
|
56 |
+ for b in bs: |
|
57 |
+ a.interact(b) |
|
56 | 58 |
|
57 |
- collide_x, collide_y = None, None |
|
59 |
+ def remove(self, object): |
|
60 |
+ pos = object.pos |
|
61 |
+ if pos in self.overlays and object in self.overlays[pos]: |
|
62 |
+ self.overlays[pos].remove(object) |
|
63 |
+ |
|
64 |
+ def move(self, object, dx,dy, update_cb): |
|
65 |
+ ox,oy = object.pos |
|
58 | 66 |
|
59 | 67 |
if abs(dx) < 2 and abs(dy) < 2: |
60 |
- ox,oy = object.pos |
|
68 |
+ self.overlays[object.pos].remove(object) |
|
69 |
+ |
|
70 |
+ collide_x, collide_y = None, None |
|
61 | 71 |
x = squeeze(ox+dx, 0, self.width-1) |
62 | 72 |
y = squeeze(oy+dy, 0, self.height-1) |
63 | 73 |
if not self.is_passable((x,y)): |
64 | 74 |
collide_x, collide_y = x,y |
65 | 75 |
x,y = ox,oy |
76 |
+ update_cb(x-ox, y-oy) |
|
77 |
+ |
|
78 |
+ if collide_x is not None: |
|
79 |
+ self.check_and_execute_bump(object, collide_x, collide_y) |
|
80 |
+ if object.pos in self.overlays: |
|
81 |
+ self.interact(object, self.overlays[object.pos]) |
|
66 | 82 |
|
83 |
+ self.overlays.setdefault((x,y), []).append(object) |
|
84 |
+ self.update_overlay(ox,oy) |
|
67 | 85 |
else: |
68 |
- ox,oy = object.pos |
|
69 |
- tx,ty = ox+dx, oy+dy |
|
70 |
- gx,gy = ox,oy |
|
71 |
- for x,y in libs.bresenham.line(ox,oy, tx,ty, 1): |
|
72 |
- if not self.is_passable((x,y)): |
|
73 |
- collide_x, collide_y = x,y |
|
86 |
+ # calculate the deltas for each step |
|
87 |
+ line = list(libs.bresenham.line(0,0, dx,dy, 0)) |
|
88 |
+ line = [(bx-ax, by-ay) for (ax,ay), (bx,by) in zip(line,line[1:])] |
|
89 |
+ print line |
|
90 |
+ for x,y in line: |
|
91 |
+ if self.move(object, x,y, update_cb) != (x,y): |
|
74 | 92 |
break |
75 |
- else: gx,gy = x,y |
|
76 |
- x,y = gx,gy |
|
93 |
+ x,y = object.pos |
|
77 | 94 |
|
78 |
- if collide_x is not None: |
|
79 |
- self.check_and_execute_bump(object, collide_x, collide_y) |
|
80 |
- |
|
81 |
- self.overlays.setdefault((x,y), []).append(object) |
|
82 |
- self.update_overlay(ox,oy) |
|
83 | 95 |
return x-ox, y-oy |
84 | 96 |
|
85 | 97 |
def update_overlay(self, x=None, y=None): |
... | ... |
@@ -102,38 +114,55 @@ class Map(object): |
102 | 114 |
|
103 | 115 |
|
104 | 116 |
def get_rgb(self, colors, fg=True,slices=(slice(0),slice(0))): |
105 |
- result = np.rollaxis(colors[slices], 2) |
|
117 |
+ result = np.rollaxis(colors, 2) |
|
106 | 118 |
return [x.transpose() for x in result] |
107 | 119 |
|
108 | 120 |
def draw(self, con, tl=(0,0)): |
121 |
+ def mv(x,y, (lx,ty)): |
|
122 |
+ return x-lx, y-ty |
|
109 | 123 |
br = tl[0]+con.width, tl[1]+con.height |
124 |
+ slices = slice(tl[0], br[0]), slice(tl[1], br[1]) |
|
110 | 125 |
|
111 | 126 |
fgcolors = self.fgcolors.astype('int') |
112 | 127 |
bgcolors = self.bgcolors.astype('int') |
113 | 128 |
color_mask = np.ones( (con.width, con.height, 3) ) |
114 | 129 |
char_mask = np.ones( (con.width, con.height) ).astype('bool') |
130 |
+ |
|
115 | 131 |
if self.pov is not None: |
116 | 132 |
origin, radius = self.pov |
133 |
+ ox, oy = origin |
|
134 |
+ if ox+radius >= br[0] or oy+radius >= br[1]: |
|
135 |
+ xmod, ymod = 0,0 |
|
136 |
+ if ox + radius >= br[0]: |
|
137 |
+ xmod = min(ox + radius - br[0], self.width - br[0]) |
|
138 |
+ if oy + radius >= br[1]: |
|
139 |
+ ymod = min(oy + radius - br[1], self.height - br[1]) |
|
140 |
+ br = br[0] + xmod, br[1] + ymod |
|
141 |
+ tl = tl[0] + xmod, tl[1] + ymod |
|
142 |
+ slices = slice(tl[0], br[0]), slice(tl[1], br[1]) |
|
117 | 143 |
def calc_mask(): |
118 | 144 |
for x in range(tl[0], br[0]): |
119 | 145 |
for y in range(tl[1], br[1]): |
120 | 146 |
if not self.fov.is_visible(origin, radius, (x,y)): |
121 |
- color_mask[x,y] = (0.25, 0.5, 0.5) |
|
122 |
- char_mask[x,y] = False |
|
147 |
+ color_mask[x-tl[0], y-tl[1]] = (0.25, 0.5, 0.5) |
|
148 |
+ char_mask[x-tl[0], y-tl[1]] = False |
|
123 | 149 |
return color_mask, char_mask |
124 |
- color_mask, char_mask = self.povcache.get( (origin,radius), calc_mask ) |
|
125 |
- fgcolors = (fgcolors * color_mask).astype('int') |
|
126 |
- bgcolors = (bgcolors * color_mask).astype('int') |
|
150 |
+ color_mask, char_mask = self.povcache.get( (origin,radius,tl), calc_mask ) |
|
151 |
+ fgcolors = (fgcolors[slices] * color_mask).astype('int') |
|
152 |
+ bgcolors = (bgcolors[slices] * color_mask).astype('int') |
|
153 |
+ else: |
|
154 |
+ fgcolors = fgcolors[slices] |
|
155 |
+ bgcolors = bgcolors[slices] |
|
127 | 156 |
|
128 |
- slices = slice(tl[0], tl[0]+con.width), slice(tl[1], tl[1]+con.height) |
|
129 |
- tc.console_fill_foreground(con.con, *self.get_rgb(fgcolors, slices=slices)) |
|
130 |
- tc.console_fill_background(con.con, *self.get_rgb(bgcolors, False,slices=slices)) |
|
157 |
+ tc.console_fill_foreground(con.con, *self.get_rgb(fgcolors)) |
|
158 |
+ tc.console_fill_background(con.con, *self.get_rgb(bgcolors, False)) |
|
131 | 159 |
|
132 | 160 |
chars = np.copy(self.map[slices]) |
133 | 161 |
for x,y in self.overlays: |
134 | 162 |
screen_x = x-tl[0] |
135 | 163 |
screen_y = y-tl[1] |
136 |
- if not char_mask[screen_x,screen_y]: continue |
|
164 |
+ if (not (tl[0] <= x < br[0])) or (not (tl[1] <= y < br[1])): continue |
|
165 |
+ elif not char_mask[screen_x,screen_y]: continue |
|
137 | 166 |
if 0 <= screen_x < con.width and 0 <= screen_y < con.height: |
138 | 167 |
obj = self.overlays[x,y][-1] |
139 | 168 |
chars[screen_x,screen_y] = obj.char |
... | ... |
@@ -183,7 +212,7 @@ class FovCache(object): |
183 | 212 |
self.fovmaps[key] = fovmap |
184 | 213 |
|
185 | 214 |
x,y = origin |
186 |
- tc.map_compute_fov(fovmap, x,y, radius) |
|
215 |
+ tc.map_compute_fov(fovmap, x,y, radius, algo=tc.FOV_DIAMOND) |
|
187 | 216 |
|
188 | 217 |
return fovmap |
189 | 218 |
|
... | ... |
@@ -10,10 +10,17 @@ class Player(libs.overlay.Actor): |
10 | 10 |
libs.overlay.Actor.__init__(self, x,y, map, adventurer) |
11 | 11 |
print 'Player\'s name is %s' % self.adventurer.name |
12 | 12 |
self.map.set_pov((self.pos, self.light_radius)) |
13 |
+ self.display = None |
|
13 | 14 |
def move(self, dx, dy): |
14 | 15 |
libs.overlay.Actor.move(self, dx,dy) |
15 | 16 |
self.map.set_pov((self.pos, self.light_radius)) |
16 | 17 |
|
18 |
+ def claim_display(self, display): |
|
19 |
+ self.display = display |
|
20 |
+ def tick(self): |
|
21 |
+ print 'player_tick' |
|
22 |
+ return libs.overlay.Actor.tick(self) |
|
23 |
+ |
|
17 | 24 |
class ArrowHandler(object): |
18 | 25 |
def __init__(self, player, eh): |
19 | 26 |
self.player = player |
... | ... |
@@ -21,28 +28,23 @@ class ArrowHandler(object): |
21 | 28 |
eh.register(tc.KEY_RIGHT,self.right) |
22 | 29 |
eh.register(tc.KEY_UP,self.up) |
23 | 30 |
eh.register(tc.KEY_DOWN,self.down) |
31 |
+ |
|
32 |
+ def do_move(self, shift, dx, dy): |
|
33 |
+ self.player.add_repeated_action(10 if shift else 1, self.player.move, dx,dy) |
|
34 |
+ |
|
24 | 35 |
def left(self, alt, shift, ctrl): |
25 |
- val = 10 if shift else 1 |
|
26 |
- if alt: |
|
27 |
- self.player.move(-val, -val) |
|
28 |
- else: |
|
29 |
- self.player.move(-val, 0) |
|
36 |
+ dx,dy = (-1,-1) if alt else (-1,0) |
|
37 |
+ self.do_move(shift, dx,dy) |
|
38 |
+ |
|
30 | 39 |
def right(self, alt, shift, ctrl): |
31 |
- val = 10 if shift else 1 |
|
32 |
- if alt: |
|
33 |
- self.player.move(val, val) |
|
34 |
- else: |
|
35 |
- self.player.move(val, 0) |
|
40 |
+ dx,dy = (1,1) if alt else (1,0) |
|
41 |
+ self.do_move(shift, dx,dy) |
|
42 |
+ |
|
36 | 43 |
def up(self, alt, shift, ctrl): |
37 |
- val = 10 if shift else 1 |
|
38 |
- if alt: |
|
39 |
- self.player.move(val, -val) |
|
40 |
- else: |
|
41 |
- self.player.move(0, -val) |
|
44 |
+ dx,dy = (1,-1) if alt else (0,-1) |
|
45 |
+ self.do_move(shift, dx,dy) |
|
46 |
+ |
|
42 | 47 |
def down(self, alt, shift, ctrl): |
43 |
- val = 10 if shift else 1 |
|
44 |
- if alt: |
|
45 |
- self.player.move(-val, val) |
|
46 |
- else: |
|
47 |
- self.player.move(0, val) |
|
48 |
+ dx,dy = (-1,1) if alt else (0,1) |
|
49 |
+ self.do_move(shift, dx,dy) |
|
48 | 50 |
|