00f730d87206ca51491b09c3a35f81804b64a449
[minwii.git] / src / pgu / tilevid.py
1 """Square tile based engine."""
2
3 from pgu.vid import *
4 import pygame
5
6 class Tilevid(Vid):
7 """Based on [[vid]] -- see for reference."""
8 def paint(self,s):
9 sw,sh = s.get_width(),s.get_height()
10 self.view.w,self.view.h = sw,sh
11
12 tiles = self.tiles
13 tw,th = tiles[0].image.get_width(),tiles[0].image.get_height()
14 w,h = self.size
15
16 if self.bounds != None: self.view.clamp_ip(self.bounds)
17
18 ox,oy = self.view.x,self.view.y
19 tlayer = self.tlayer
20 blayer = self.blayer
21 alayer = self.alayer
22 sprites = self.sprites
23
24 blit = s.blit
25 yy = - (self.view.y%th)
26 my = (oy+sh)/th
27 if (oy+sh)%th: my += 1
28
29 if blayer != None:
30 for y in xrange(oy/th,my):
31 if y >=0 and y < h:
32 trow = tlayer[y]
33 brow = blayer[y]
34 arow = alayer[y]
35 xx= - (self.view.x%tw)
36 mx = (ox+sw)/tw
37 #if (ox+sh)%tw: mx += 1
38 for x in xrange(ox/tw,mx+1):
39 if x >=0and x<w:
40 blit(tiles[brow[x]].image,(xx,yy))
41 blit(tiles[trow[x]].image,(xx,yy))
42 arow[x]=0
43 xx += tw
44 yy+=th
45 else:
46 for y in xrange(oy/th,my):
47 if y >=0 and y<h:
48 trow = tlayer[y]
49 arow = alayer[y]
50 xx= - (self.view.x%tw)
51 mx = (ox+sw)/tw
52 #if (ox+sh)%tw: mx += 1
53 for x in xrange(ox/tw,mx+1):
54 if x >=0 and x<w:
55 blit(tiles[trow[x]].image,(xx,yy))
56 arow[x]=0
57 xx += tw
58 yy+=th
59
60 for s in sprites:
61 s.irect.x = s.rect.x-s.shape.x
62 s.irect.y = s.rect.y-s.shape.y
63 blit(s.image,(s.irect.x-ox,s.irect.y-oy))
64 s.updated=0
65 s._irect = Rect(s.irect)
66 #s._rect = Rect(s.rect)
67
68 self.updates = []
69 self._view = pygame.Rect(self.view)
70 return [Rect(0,0,sw,sh)]
71
72 def update(self,s):
73 sw,sh = s.get_width(),s.get_height()
74 self.view.w,self.view.h = sw,sh
75
76 if self.bounds != None: self.view.clamp_ip(self.bounds)
77 if self.view.x != self._view.x or self.view.y != self._view.y:
78 return self.paint(s)
79
80 ox,oy = self.view.x,self.view.y
81 sw,sh = s.get_width(),s.get_height()
82 w,h = self.size
83 tlayer = self.tlayer
84 blayer = self.blayer
85 alayer = self.alayer
86 tiles = self.tiles
87 tw,th = tiles[0].image.get_width(),tiles[0].image.get_height()
88 sprites = self.sprites
89 blit = s.blit
90
91 us = []
92
93 #mark places where sprites have moved, or been removed
94
95 ss = self.sprites.removed
96 self.sprites.removed = []
97 ss.extend(sprites)
98 for s in ss:
99 #figure out what has been updated.
100 s.irect.x = s.rect.x-s.shape.x
101 s.irect.y = s.rect.y-s.shape.y
102 if (s.irect.x != s._irect.x or s.irect.y != s._irect.y
103 or s.image != s._image):
104 #w,h can be skipped, image covers that...
105 s.updated = 1
106 if s.updated:
107 r = s._irect
108 y = max(0,r.y/th)
109 yy = min(h,r.bottom/th+1)
110 while y < yy:
111 x = max(0,r.x/tw)
112 xx = min(w,r.right/tw+1)
113 while x < xx:
114 if alayer[y][x] == 0:
115 self.updates.append((x,y))
116 alayer[y][x]=1
117 x += 1
118 y += 1
119
120 r = s.irect
121 y = max(0,r.y/th)
122 yy = min(h,r.bottom/th+1)
123 while y < yy:
124 x = r.x/tw
125 xx = min(w,r.right/tw+1)
126 while x < xx:
127 if alayer[y][x]==0:
128 alayer[y][x]=2
129 self.updates.append((x,y))
130 x += 1
131 y += 1
132
133
134 #mark sprites that are not being updated that need to be updated because
135 #they are being overwritte by sprites / tiles
136 for s in sprites:
137 if s.updated==0:
138 r = s.irect
139 y = max(0,r.y/th)
140 yy = min(h,r.bottom/th+1)
141 while y < yy:
142 x = max(0,r.x/tw)
143 xx = min(w,r.right/tw+1)
144 while x < xx:
145 if alayer[y][x]==1:
146 s.updated=1
147 x += 1
148 y += 1
149
150
151 for u in self.updates:
152 x,y=u
153 xx,yy=x*tw-ox,y*th-oy
154 if alayer[y][x] == 1:
155 if blayer != None: blit(tiles[blayer[y][x]].image,(xx,yy))
156 blit(tiles[tlayer[y][x]].image,(xx,yy))
157 alayer[y][x]=0
158 us.append(Rect(xx,yy,tw,th))
159
160 for s in sprites:
161 if s.updated:
162 blit(s.image,(s.irect.x-ox, s.irect.y-oy))
163 s.updated=0
164 s._irect = Rect(s.irect)
165 s._image = s.image
166
167 self.updates = []
168 return us
169
170 def view_to_tile(self,pos):
171 x,y = pos
172 tiles = self.tiles
173 tw,th = tiles[0].image.get_width(),tiles[0].image.get_height()
174 return x/tw,y/th
175
176 def tile_to_view(self,pos):
177 x,y = pos
178 tiles = self.tiles
179 tw,th = tiles[0].image.get_width(),tiles[0].image.get_height()
180 x,y = x*tw, y*th
181 return x,y
182
183
184 def screen_to_tile(self,pos):
185 x,y = pos
186 x,y = x+self.view.x,y+self.view.y
187 return self.view_to_tile((x,y))
188
189 def tile_to_screen(self,pos):
190 x,y = pos
191 x,y = self.tile_to_view(pos)
192 x,y = x - self.view.x, y - self.view.y
193 return x,y
194
195 # vim: set filetype=python sts=4 sw=4 noet si :