Agregadas dos pantallas más
[tajundrathegame.git] / qwesprites.py
blobcf2cf9182751c5930882e77bd678da6255a4fea7
1 # Quick W Engine
2 # encoding: UTF-8
3 import pygame
4 import math
5 import random
8 class qweSprite(pygame.sprite.Sprite):
9 dx=dy=x=y=0
10 w=h=32
11 alive=True
12 LevelFinished=False
13 in_ground=False
14 FRICTION_AIR=(0.2,0.2)
15 FRICTION_FLOOR=(8,8)
16 FRICTION_CEIL=(0.1,4)
17 GRAVITY=5
18 BOUNCE=-.1
19 RADIUS=16
20 psx=-1
21 psy=-1
22 ShowLife=MaxLife=Life=240
23 DIE_IMG='pernil.png'
24 accum_ms=1000
25 accum_dist=1000
27 #MAX_ACCUMMS=200
28 #MAX_ACCUMDIST=1000
30 MAX_ACCUMMS=100
31 MAX_ACCUMDIST=500
33 #MAX_ACCUMMS=50
34 #MAX_ACCUMDIST=250
36 LifeCollisionCost=0
37 LifeCollisionSpriteCost=2
38 MARGIN_LEFT=+2
39 MARGIN_RIGHT=-2
40 MARGIN_TOP=+1
41 MARGIN_BOTTOM=-1
42 fcount=0
43 SOLID=True
44 FSOLID=True
46 Item="?"
47 ItemTime=0
49 def __init__(self, stage):
50 pygame.sprite.Sprite.__init__(self)
51 stage.sprites+=[self]
53 def move(self,x,y):
54 self.x+=x
55 self.y+=y
57 self.rect=pygame.Rect(self.x,self.y,self.w,self.h)
59 def selectImage(self):
60 return self.image
62 def die(self,screen):
63 Life(screen,(int(self.x),int(self.y)),self.DIE_IMG,self.MaxLife/4.0)
66 def draw(self,screen,list_rects=None):
67 if self.accum_ms>0:
68 if list_rects:
69 if self.rect.collidelist(list_rects)==.1: return
70 self.fcount+=1
71 if self.fcount>10/(self.Life+1):
72 self.fcount=4
73 screen.blit(self.selectImage(), self.rect)
74 if self.ShowLife>self.Life or (self.Life < 60 and self.ShowLife>0):
75 if self.ShowLife<0: self.ShowLife=0
76 x,y,h,w=self.rect
77 pp=100.0*self.ShowLife/self.MaxLife
78 pp=pp+math.log(1+1.9*self.ShowLife/self.MaxLife)*100.0
79 if pp>200.0:
80 pp=200
81 if pp>100.0:
82 pp1=100
83 pp2=pp-100
84 else:
85 pp1=pp
86 pp2=0
88 w-=8
89 x+=1
90 y+=0
91 p1=x,y
92 p2=x+pp1*w/100.0,y
93 p1a=x,y+1
94 p2a=x+pp2*w/100.0,y+1
96 p=255.0*pp1/100.0
97 if pp2:
98 p=255.0*pp2/100.0
99 pygame.draw.line(screen, (255-p,255,0) , p1a, p2a,1)
100 pygame.draw.line(screen, (255-p,255,0) , p1, p2,1)
101 else:
102 pygame.draw.line(screen, (255,p,0) , p1, p2,1)
104 def tickms(self, ms, stage):
105 if not self.alive:
106 return []
108 d=math.sqrt(self.dx*self.dx+self.dy*self.dy)
109 self.accum_ms+=ms
110 self.accum_dist+=d*ms
111 if self.ShowLife>self.Life:
112 self.accum_dist+=(self.ShowLife-self.Life)
114 if self.Life<1:
115 self.accum_dist+=10/(self.Life+0.1)
117 if self.accum_ms>self.MAX_ACCUMMS or \
118 self.accum_dist>self.MAX_ACCUMDIST:
119 ms=self.accum_ms
120 self.accum_ms=0
121 self.accum_dist=0
123 rect1=pygame.Rect(self.rect)
124 if (self.ItemTime>0):
125 self.ItemTime-=ms
126 else:
127 self.ItemTime=0
129 if (self.Life<0):
130 self.alive=False
131 self.die(stage)
132 else:
133 self.Life-=ms/1000.0
135 if self.ShowLife>self.Life:
136 self.ShowLife-=ms/100.0
137 if self.ShowLife<self.Life:
138 self.ShowLife=self.Life
140 self.checkpos(stage,ms)
141 self.move(self.dx*ms/1000.0,self.dy*ms/1000.0)
142 self.dx/=1+self.FRICTION_AIR[0]*ms/1000.0
143 self.dy/=1+self.FRICTION_AIR[1]*ms/1000.0
145 rect2=self.rect
146 self.psx,self.psy=self.getpspoint(stage,0,0);
148 return [rect1.union(rect2)]
149 else:
150 return []
153 def getpspoint(self,stage,px,py):
154 sx,sy=stage.BlockSize
155 x,y,w,h=self.rect
157 if px>0: x0=x+px
158 elif px<0: x0=x+w+px
159 else: x0=x+w/2
161 if py>0: y0=y+py
162 elif py<0: y0=y+h+py
163 else: y0=y+h/2
165 x0=int(x0)/sx
166 y0=int(y0)/sy
168 return (x0,y0)
170 def collision(self,stage,x,y,char):
171 if self.ItemTime==0:
172 Pantalla=stage.StageData
174 if char=='P':
175 self.alive=False
176 self.LevelFinished=True
178 if not self.Item:
179 if char=='z':
180 self.Item=char
181 self.ItemTime=1000
182 stage.setCh(x,y,' ')
183 stage.checkPortal()
184 else:
185 if char=='Z' and self.Item=='z' and stage.getCh(x,y-1)==' ':
186 stage.setCh(x,y-1,'z')
187 stage.checkPortal()
188 self.ItemTime=1000
189 self.Item=''
192 def checkcell(self,stage,px,py):
193 Pantalla=stage.StageData
195 x0,y0=self.getpspoint(stage,px,py);
197 if y0<0 and x0>=0 and x0<len(Pantalla[0]): return ' '
198 if y0>=0 and y0<len(Pantalla):
199 if x0>=0 and x0<len(Pantalla[y0]):
200 ch=Pantalla[y0][x0]
201 self.collision(stage,x0,y0,ch)
203 return ch
205 return 't'
207 def checkpos(self,stage,ms):
208 self.in_ground=False
210 if self.Life<=0.5: return
211 for sprite in stage.sprites:
212 if sprite!=self and sprite.RADIUS>0 and sprite.Life>0.5:
213 if ( math.fabs(sprite.psx-self.psx)<=1
214 and math.fabs(sprite.psy-self.psy)<=1):
215 x,y,w,h=self.rect
216 sx,sy,sw,sh=sprite.rect
218 min_d=self.RADIUS+sprite.RADIUS
220 ax=x-sx;ay=y-sy;
221 d1=math.sqrt(ax*ax+ay*ay)
222 if d1<min_d:
223 x+=self.dx/1000.0
224 y+=self.dy/1000.0
225 sx+=sprite.dx/1000.0
226 sy+=sprite.dy/1000.0
228 ax=x-sx;ay=y-sy;
229 d2=math.sqrt(ax*ax+ay*ay)
230 if d2<=d1:
231 sdx=sprite.dx
232 sdy=sprite.dy
233 if sprite.SOLID and self.FSOLID:
234 sprite.dx=self.dx
235 sprite.dy=self.dy
237 if self.SOLID and sprite.FSOLID:
238 self.dx=sdx
239 self.dy=sdy
241 if self.Life<900:
242 self.Life-=sprite.LifeCollisionSpriteCost
243 if self.ShowLife>0:
244 self.ShowLife=self.Life+10
246 if sprite.Life<900:
247 sprite.Life-=self.LifeCollisionSpriteCost
248 if sprite.ShowLife>0:
249 sprite.ShowLife=sprite.Life+10
252 if d2<=d1+0.1:
253 self.in_ground=True
254 x,y,w,h=self.rect
255 ax=x-sx;ay=y-sy;
256 d1=math.sqrt(ax*ax+ay*ay)+1
257 if self.SOLID and sprite.FSOLID:
258 self.dx+=20*ax/d1
259 self.dy+=20*ay/d1
261 if sprite.SOLID and self.FSOLID:
262 sprite.dx-=20*ax/d1
263 sprite.dy-=20*ay/d1
267 # Colisión Horizontal
268 if ( (self.checkcell(stage,self.MARGIN_RIGHT,0)!=' ' and self.dx>=0) or
269 (self.checkcell(stage,self.MARGIN_RIGHT,12)!=' ' and self.dx>=0) or
270 (self.checkcell(stage,self.MARGIN_RIGHT,-12)!=' ' and self.dx>=0) ) :
271 if self.Life<900: self.Life-=self.LifeCollisionCost
272 self.move(-self.dx*ms/1000.0-.1,0)
273 if (self.BOUNCE>0): self.dx*=-self.BOUNCE
274 else: self.dx/=1-self.BOUNCE
276 if ( (self.checkcell(stage,self.MARGIN_LEFT,0)!=' ' and self.dx<=0) or
277 (self.checkcell(stage,self.MARGIN_LEFT,12)!=' ' and self.dx<=0) or
278 (self.checkcell(stage,self.MARGIN_LEFT,-12)!=' ' and self.dx<=0) ) :
279 if self.Life<900: self.Life-=self.LifeCollisionCost
280 self.move(-self.dx*ms/1000.0+.1,0)
281 if (self.BOUNCE>0): self.dx*=-self.BOUNCE
282 else: self.dx/=1-self.BOUNCE
284 #if ( (self.checkcell(stage,-4,0)!=' ' and self.dx>0) or
285 # (self.checkcell(stage,+4,0)!=' ' and self.dx<0) ) :
286 # self.dx/=1+5*ms/1000.0
289 # Control de hundimiento
290 if self.dy>=0:
291 if (self.checkcell(stage,self.MARGIN_LEFT+4,self.MARGIN_BOTTOM-1)!=' '
292 or self.checkcell(stage,self.MARGIN_RIGHT-4,self.MARGIN_BOTTOM-1)!=' '):
293 self.move(0,-1)
294 self.dy=0
296 # Colisión de techo
297 elif self.dy<0:
298 if (self.checkcell(stage,self.MARGIN_LEFT+4,self.MARGIN_TOP)!=' ' or
299 self.checkcell(stage,self.MARGIN_RIGHT-4,self.MARGIN_TOP)!=' ' or
300 self.checkcell(stage,0,self.MARGIN_TOP)!=' '):
302 if self.Life<900: self.Life-=self.LifeCollisionCost
303 self.move(0,-self.dy*ms/1000.0)
304 if (self.BOUNCE>0): self.dy*=-self.BOUNCE
305 else: self.dy/=1-self.BOUNCE
306 self.dx/=1+self.FRICTION_CEIL[0]*ms/1000.0
307 self.dy/=1+self.FRICTION_CEIL[1]*ms/1000.0
308 if self.checkcell(stage,0,+2)!=' ' and self.dy<0:
309 self.dx/=1+self.FRICTION_CEIL[0]*ms/1000.0
310 self.dy/=1+self.FRICTION_CEIL[1]*ms/1000.0
311 if self.checkcell(stage,0,+3)!=' ' and self.dy<0:
312 self.dy=0
316 # Colisión suelo
317 if (self.checkcell(stage,self.MARGIN_LEFT+4,self.MARGIN_BOTTOM)!=' '
318 or self.checkcell(stage,self.MARGIN_RIGHT-4,self.MARGIN_BOTTOM)!=' '):
319 self.dx/=1+self.FRICTION_FLOOR[0]*ms/1000.0
320 if self.dy>0:
321 if self.Life<900: self.Life-=self.LifeCollisionCost
322 if (self.BOUNCE>0): self.dy*=-self.BOUNCE
323 else: self.dy/=1-self.BOUNCE
324 self.dy/=1+self.FRICTION_FLOOR[1]*ms/1000.0
325 self.move(0,-self.dy*ms/1000.0)
327 elif self.dy<0:
328 pass
330 self.in_ground=True
331 else:
332 # Gravedad
333 self.dy+=self.GRAVITY
335 if self.Life<0.5: self.Life=0.5
336 if self.Life>self.MaxLife*1.5: self.Life=self.MaxLife*1.5
338 class qweText(qweSprite):
339 FONT=None
340 GRAVITY=0
341 SOLID=False
342 FSOLID=False
343 Life=1000
344 LifeCollisionSpriteCost=0
345 ShowLife=0
346 RADIUS=0
348 def __init__(self, stage,x,y,txt,font,color):
350 qweSprite.__init__(self,stage)
351 self.FONT=font
353 self.image=font.render(txt, True, color)
355 self.rect = self.image.get_rect()
357 self.x,self.y,self.w,self.h=self.rect
358 self.x=x
359 self.y=y
361 def collision(self,stage,x,y,char):
362 return
364 def checkcell(self,stage,px,py):
365 return ' '
367 def checkpos(self,stage,ms):
368 return
371 global qweTextBasic_font
372 qweTextBasic_font=None
373 global qweTextBIG_font
374 qweTextBIG_font=None
376 class qweTextBasic(qweText):
377 def __init__(self, stage,x,y,txt):
378 global qweTextBasic_font
379 if not qweTextBasic_font:
380 qweTextBasic_font=pygame.font.Font(None,15)
382 color=(0,255,0)
383 qweText.__init__(self,stage,x,y,txt,qweTextBasic_font,color)
385 class qweTextBIG(qweText):
386 def __init__(self, stage,x,y,txt):
387 qweSprite.__init__(self,stage)
388 global qweTextBIG_font
389 if not qweTextBIG_font:
390 qweTextBIG_font=pygame.font.Font(None,64)
392 self.FONT=qweTextBIG_font
394 self.image1=qweTextBIG_font.render(txt, True, (0,0,0))
395 self.image2=qweTextBIG_font.render(txt, True, (255,255,255))
396 w,h = self.image1.get_size()
397 w+=5
398 h+=5
399 self.image=pygame.Surface((w,h),pygame.SRCALPHA).convert_alpha()
400 self.image.fill((0,0,0,0))
401 self.image.blit(self.image1,(5,5))
402 self.image.blit(self.image2,(0,0))
405 self.rect = self.image.get_rect()
407 self.x,self.y,self.w,self.h=self.rect
408 self.x=x-w/2
409 self.y=y-h/2
412 class Tajundra(qweSprite):
413 image_flip=None
414 estado=0
415 estado_ms=0
416 MARGIN_LEFT=+8
417 MARGIN_RIGHT=-8
418 MARGIN_TOP=+1
419 MARGIN_BOTTOM=-1
420 RADIUS=10
421 BOUNCE=0
422 Item=None
423 DIE_IMG='platano.png'
424 MAX_ACCUMMS=50
425 MAX_ACCUMDIST=250
427 def __init__(self, stage):
429 qweSprite.__init__(self,stage)
430 self.image_right = pygame.image.load('tajuA1.png')
431 self.image_left=pygame.transform.flip(self.image_right,True,False)
433 self.imageb_right = pygame.image.load('tajuA2.png')
434 self.imageb_left=pygame.transform.flip(self.imageb_right,True,False)
437 self.image=self.image_right
438 self.rect = self.image.get_rect()
439 pos=stage.simbolos['@'][0]
440 del stage.simbolos['@'][0]
441 self.rect.bottomright = pos
442 self.rect=self.rect.move(stage.BlockSize)
443 self.x,self.y,self.w,self.h=self.rect
445 def selectImage(self):
446 dx=self.dx
447 if self.estado==0:
448 if dx<0:
449 self.image=self.image_left
450 else:
451 self.image=self.image_right
452 else:
453 if dx<0:
454 self.image=self.imageb_left
455 else:
456 self.image=self.imageb_right
457 self.estado_ms+=1
458 if self.estado_ms>20:
459 self.estado_ms=0
460 if self.estado==0:
461 self.estado=1
462 else:
463 self.estado=0
464 return self.image
470 class Dragon(qweSprite):
471 image_flip=None
472 estado=0
473 estado_ms=0
474 MAX_ACCUMMS=200
475 MAX_ACCUMDIST=1000
477 def __init__(self, stage):
479 qweSprite.__init__(self,stage)
480 self.image_left = pygame.image.load('dragonN1.png')
481 self.image_right=pygame.transform.flip(self.image_left,True,False)
483 self.imageb_left = pygame.image.load('dragonN2.png')
484 self.imageb_right=pygame.transform.flip(self.imageb_left,True,False)
487 self.image=self.image_right
488 self.rect = self.image.get_rect()
489 pos=stage.simbolos['$'][0]
490 del stage.simbolos['$'][0]
492 self.rect.bottomright = pos
493 self.rect=self.rect.move(stage.BlockSize)
494 self.x,self.y,self.w,self.h=self.rect
496 def selectImage(self):
497 dx=self.dx
498 if self.estado==0:
499 if dx<0:
500 self.image=self.image_left
501 else:
502 self.image=self.image_right
503 else:
504 if dx<0:
505 self.image=self.imageb_left
506 else:
507 self.image=self.imageb_right
508 self.estado_ms+=1
509 if self.estado_ms>20:
510 self.estado_ms=0
511 if self.estado==0:
512 self.estado=1
513 else:
514 self.estado=0
515 return self.image
519 class LanzaBolas(qweSprite):
520 image_flip=None
521 MAX_ACCUMMS=200
522 MAX_ACCUMDIST=2000
524 estado=0
525 estado_ms=0
526 BOUNCE=0
527 DIE_IMG='safanoria.png'
528 def __init__(self, stage):
530 qweSprite.__init__(self,stage)
531 self.image = pygame.image.load('lanzabolas1.png')
533 self.rect = self.image.get_rect()
534 pos=stage.simbolos['|'][0]
535 del stage.simbolos['|'][0]
537 self.rect.bottomright = pos
538 self.rect=self.rect.move(stage.BlockSize)
539 self.x,self.y,self.w,self.h=self.rect
540 self.estado_ms=random.randint(6000,12000)
542 def selectImage(self):
543 return self.image
545 def tickms(self, ms, stage):
547 v=qweSprite.tickms(self, ms, stage)
548 self.estado_ms+=ms
549 if self.estado_ms>10000 and self.Life>10:
550 random.seed()
551 self.estado_ms=random.randint(0,1000)
552 r=random.randint(-1000,1000)/3.0
553 disparo=Bola(stage,(int(self.x),int(self.y)),r,-200)
554 disparo.move(0,-10)
555 disparo.GRAVITY=1
557 return v
561 class qweShoot(qweSprite):
562 estado=0
563 estado_ms=0
564 FRICTION_AIR=(0.0,0.0)
565 FRICTION_FLOOR=(0.0,0.0)
566 FRICTION_CEIL=(0.0,0.0)
567 GRAVITY=0
568 BOUNCE=.5
569 MaxLife=Life=2.0
570 ShowLife=0
571 LifeCollisionCost=1
572 LifeCollisionSpriteCost=10
574 fcount=0
575 accum_ms=0
577 MARGIN_LEFT=+10
578 MARGIN_RIGHT=-10
579 MARGIN_TOP=+10
580 MARGIN_BOTTOM=-10
582 def __init__(self, stage, pos,dx,dy):
584 qweSprite.__init__(self,stage)
585 self.image = pygame.image.load('bola1.png')
587 self.rect = self.image.get_rect()
589 self.rect.topleft = pos
590 self.dx=dx
591 self.dy=dy
592 self.x,self.y,self.w,self.h=self.rect
593 d=math.sqrt(dx*dx+dy*dy)+5
594 self.tickms(1000/d,stage);
596 def collision(self,stage,x,y,char):
597 qweSprite.collision(self,stage,x,y,char)
598 if self.ItemTime==0:
599 nchar=char
601 if char=='M': nchar='N'
602 if char=='N': nchar='m'
603 if char=='m': nchar='n'
604 if char=='n': nchar=' '
606 if char!=nchar:
607 stage.setCh(x,y,nchar)
608 self.Life-=1
609 self.ItemTime=1000
613 def die(self,screen):
614 pass
616 class Bola(qweShoot):
617 GRAVITY=20
618 BOUNCE=.5
619 MaxLife=Life=12.0
620 LifeCollisionCost=1
621 RADIUS=5
622 MAX_ACCUMMS=1000
623 MAX_ACCUMDIST=1000
625 class Hacha(qweShoot):
626 FRICTION_AIR=(0.5,0.0)
627 BOUNCE=.8
628 MaxLife=60
629 Life=2
630 LifeCollisionCost=0.1
631 LifeCollisionSpriteCost=10
632 fcountrot=0
633 angle=0
634 GRAVITY=5
635 RADIUS=10
637 MARGIN_LEFT=+12
638 MARGIN_RIGHT=-12
639 MARGIN_TOP=+7
640 MARGIN_BOTTOM=-7
642 time_elapsed=0
644 def __init__(self, stage, pos,dx,dy):
646 qweSprite.__init__(self,stage)
647 self.image1 = pygame.image.load('hacha1.png')
648 if dx<0: self.image1=pygame.transform.flip(self.image1, True, False)
649 self.image = self.image1.copy()
650 self.rect = self.image.get_rect()
652 self.rect.topleft = pos
653 self.dx=dx
654 self.dy=dy
655 self.x,self.y,self.w,self.h=self.rect
658 def draw(self,screen,lr=None):
659 self.fcountrot+=1
660 if self.Life>0 and self.fcountrot>5/self.Life:
661 self.image=pygame.transform.rotate(self.image1, self.angle)
662 if self.dx>0:
663 self.angle-=90
664 else:
665 self.angle+=90
666 self.fcountrot=0
667 if self.Life>2:
668 self.SOLID=False
669 else:
670 self.SOLID=True
672 qweShoot.draw(self,screen,lr)
674 def tickms(self, ms, stage):
675 if self.Life>2:
676 self.dx*=1.01
677 self.dy*=1.01
678 self.time_elapsed+=ms
679 if self.time_elapsed<50:
680 self.FSOLID=False
681 else:
682 self.FSOLID=True
684 v=qweSprite.tickms(self, ms, stage)
685 return v
687 def collision(self,stage,x,y,char):
688 qweShoot.collision(self,stage,x,y,char)
690 if char=='B' and x>self.psx and self.dx>0 \
691 and stage.getCh(x+1,y)==' ' and stage.getCh(x+1,y+1)!=' ':
692 stage.setCh(x,y,' ')
693 stage.setCh(x+1,y,'B')
694 self.Life-=1
696 if char=='B' and x<self.psx and self.dx<0 \
697 and stage.getCh(x-1,y)==' ' and stage.getCh(x-1,y+1)!=' ':
698 stage.setCh(x,y,' ')
699 stage.setCh(x-1,y,'B')
700 self.Life-=1
703 class Life(qweShoot):
704 FRICTION_AIR=(10.0,10.0)
705 BOUNCE=-.8
706 ShowLife=MaxLife=Life=10
707 LifeCollisionCost=0
708 LifeCollisionSpriteCost=-2
710 GRAVITY=1
711 SOLID=False
712 FSOLID=False
714 RADIUS=0
716 MARGIN_LEFT=+4
717 MARGIN_RIGHT=-4
718 MARGIN_TOP=+4
719 MARGIN_BOTTOM=-4
721 def __init__(self, stage, pos,imgfile, life):
723 qweSprite.__init__(self,stage)
725 self.image1 = pygame.image.load(imgfile)
726 self.image = self.image1.copy()
727 self.rect = self.image.get_rect()
728 self.ShowLife=self.MaxLife=self.Life=life
730 self.rect.topleft = pos
731 self.dx=0
732 self.dy=-20
733 self.x,self.y,self.w,self.h=self.rect
734 self.tickms(5,stage);
736 def tickms(self, ms, stage):
737 if self.RADIUS<16:
738 self.RADIUS+=ms/500.0
740 v=qweSprite.tickms(self, ms, stage)
741 if self.psx<0: self.move(8,0)
742 if self.psx>=20: self.move(-8,0)
744 if self.psy<0: self.move(0,8)
745 if self.psy>=15: self.move(0,-8)
746 return v