schiff16.py :  » Game-2D-3D » pygamebook » src » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Game 2D 3D » pygamebook 
pygamebook » src » schiff16.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

#         - - - - - -
# example with vector class for my pygamebook
# LICENSE: Gnu General Public License (GPL)
# includes vec2d class from www.pygame.org
# AUTHOR: (from the game, not from the vec2dclass): Horst JENS
# email: horst.jens@gmail.com
# web: http://www.spielend-programmieren.at
#        - - - - - - - 

#       
#       This program is free software; you can redistribute it and/or modify
#       it under the terms of the GNU General Public License as published by
#       the Free Software Foundation; either version 2 of the License, or
#       (at your option) any later version.
#       
#       This program is distributed in the hope that it will be useful,
#       but WITHOUT ANY WARRANTY; without even the implied warranty of
#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#       GNU General Public License for more details.
#       
#       You should have received a copy of the GNU General Public License
#       along with this program; if not, write to the Free Software
#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#       MA 02110-1301, USA.







#FIXME: rotation ordentlich machen, ohne -90 und *-1
#FIXME: self.rect.center - oldcenter in Ordnung bringen
#FIXME: tracer kaputt wegen dirtyrecs-remove
#FIXME: Modus sinnvoll machen (derzeit nur space sinnvoll)
#FIXME: spacemove und newmoving vereinheitlichen
#FIXME: division by Zero kapieren
#FIXME: myfont eine globale Variable oder Konstante machen (im Sprite Text)



#TODO: 4 Player / Bots / AI !
#TODO: Tastaturkrzel sinnvoller (links/rechts), auf mac/netbook testen. Vorschlag: player1: wasd, player2: ijkl oder cursor
#TODO: verstehen: wird ein pos-Vektor als positionsargument bergeben wandert das ding mit (siehe victory)
#TODO: GUI oder config

#TODO: Reibung, 
#TODO: optional sich in die Kurve legen (x-schrumpfen) bei rotation-speed<>0
#TODO: Wind
#TODO: Feuer, Riffe oder gefhrlicher Rand
#TODO: Segelschiffe, schiessen seitlich, eventuell Buggeschtz, schwaches Heckgeschtz(e)
#TODO: Rammen (Rammwinkel)
#TODO: mehr Segelschiff-sim
#TODO: Vektoren schner machen, mit Pfeilspitzen oder Dreiecke
#TODO: tracer-recs in sprite-liste abspeichern, verfrben und verschwinden lassen
#TODO: wenn lfleck getroffen, schneller / grsser / driften


#Vorschlge
#drehen schneller
#dauerfeuer bei gedrckter Taste
#Steuerung ohne floating ?
#basis die dich schtz
#Heilung optional



#done: 4 Player !
#done: feuervektorliste, gegnervektorliste
#done: Mausvecktor und Positionsvektor mit variabler Lnge
#done: Vektorenkreise schn an screenrectseiten ausrichten (Blocksatz)
#done: Vektoren wachsen aus kreis raus (bei ship-coll)
#done: seltsamer zoom-fehler debugt (textsize erhht anstatt rotozoom bei text verwendet)
#done: Text-classe die schn zoomt und davon abgeleitete hitpointtext mit hitpoint-update
#done: hitpointtext machen
#done: gelber Damagetext bei lflecken (danger)
#done: Vectorsprite holt sich koordinaten von bosssprite (Tank)
#done: Victory und Looser Text, vorbereitet fr mehr als 2 Spieler
#done: lflecken "fressen" Blle
#done: 4 lflecken, am Rand
#done: player2 startet rechts unten
#done: finale Explosion
#done: 2. Vektorspirte mehr nach rechts
#done: unglieche tick-zeit..kugeln fliegen unterschiedlich schnell (?)
#done: schiffe stoppen total bei zusammenstoss
#done: schsse bremsen (gegenvektor), nicht nur verschieben der Position
#done: schwimmendes Feuer (sehr primitv)
#done:  hitpoints-balken, trefferanzeige
#done: Kugeln haben Farbe von Bosssprite
#done: keine Schmutzflecken mehr. Vorher: entstehen bei speed und schiessen.
#done: ball und schuss
#done: screen und screenrect
#done: move-vektor
#done: Forcevektor
#done: Mausvektor
#done: brems-steuerungslichter
#done: speedlimit
#done: modus umschalten mit m
#done: time-based movement
#done: 2 Tracer Linien von den Eckpunkten, wie Kondensstreifen
from __future__ import division
import operator # fr vec2d
import math     # fr vec2d
# fr mich
import pygame   
import random
random.seed() # init random generator with time or other random value
#import vec2d

class vec2d(object):
    """2d vector class, supports vector and scalar operators,
       and also provides a bunch of high level functions
       """
    __slots__ = ['x', 'y']
 
    def __init__(self, x_or_pair, y = None):
        if y == None:
            self.x = x_or_pair[0]
            self.y = x_or_pair[1]
        else:
            self.x = x_or_pair
            self.y = y
 
    def __len__(self):
        return 2
 
    def __getitem__(self, key):
        if key == 0:
            return self.x
        elif key == 1:
            return self.y
        else:
            raise IndexError("Invalid subscript "+str(key)+" to vec2d")
 
    def __setitem__(self, key, value):
        if key == 0:
            self.x = value
        elif key == 1:
            self.y = value
        else:
            raise IndexError("Invalid subscript "+str(key)+" to vec2d")
 
    # String representaion (for debugging)
    def __repr__(self):
        return 'vec2d(%s, %s)' % (self.x, self.y)
    
    # Comparison
    def __eq__(self, other):
        if hasattr(other, "__getitem__") and len(other) == 2:
            return self.x == other[0] and self.y == other[1]
        else:
            return False
    
    def __ne__(self, other):
        if hasattr(other, "__getitem__") and len(other) == 2:
            return self.x != other[0] or self.y != other[1]
        else:
            return True
 
    def __nonzero__(self):
        return self.x or self.y
 
    # Generic operator handlers
    def _o2(self, other, f):
        "Any two-operator operation where the left operand is a vec2d"
        if isinstance(other, vec2d):
            return vec2d(f(self.x, other.x),
                         f(self.y, other.y))
        elif (hasattr(other, "__getitem__")):
            return vec2d(f(self.x, other[0]),
                         f(self.y, other[1]))
        else:
            return vec2d(f(self.x, other),
                         f(self.y, other))
 
    def _r_o2(self, other, f):
        "Any two-operator operation where the right operand is a vec2d"
        if (hasattr(other, "__getitem__")):
            return vec2d(f(other[0], self.x),
                         f(other[1], self.y))
        else:
            return vec2d(f(other, self.x),
                         f(other, self.y))
 
    def _io(self, other, f):
        "inplace operator"
        if (hasattr(other, "__getitem__")):
            self.x = f(self.x, other[0])
            self.y = f(self.y, other[1])
        else:
            self.x = f(self.x, other)
            self.y = f(self.y, other)
        return self
 
    # Addition
    def __add__(self, other):
        if isinstance(other, vec2d):
            return vec2d(self.x + other.x, self.y + other.y)
        elif hasattr(other, "__getitem__"):
            return vec2d(self.x + other[0], self.y + other[1])
        else:
            return vec2d(self.x + other, self.y + other)
    __radd__ = __add__
    
    def __iadd__(self, other):
        if isinstance(other, vec2d):
            self.x += other.x
            self.y += other.y
        elif hasattr(other, "__getitem__"):
            self.x += other[0]
            self.y += other[1]
        else:
            self.x += other
            self.y += other
        return self
 
    # Subtraction
    def __sub__(self, other):
        if isinstance(other, vec2d):
            return vec2d(self.x - other.x, self.y - other.y)
        elif (hasattr(other, "__getitem__")):
            return vec2d(self.x - other[0], self.y - other[1])
        else:
            return vec2d(self.x - other, self.y - other)
    def __rsub__(self, other):
        if isinstance(other, vec2d):
            return vec2d(other.x - self.x, other.y - self.y)
        if (hasattr(other, "__getitem__")):
            return vec2d(other[0] - self.x, other[1] - self.y)
        else:
            return vec2d(other - self.x, other - self.y)
    def __isub__(self, other):
        if isinstance(other, vec2d):
            self.x -= other.x
            self.y -= other.y
        elif (hasattr(other, "__getitem__")):
            self.x -= other[0]
            self.y -= other[1]
        else:
            self.x -= other
            self.y -= other
        return self
 
    # Multiplication
    def __mul__(self, other):
        if isinstance(other, vec2d):
            return vec2d(self.x*other.x, self.y*other.y)
        if (hasattr(other, "__getitem__")):
            return vec2d(self.x*other[0], self.y*other[1])
        else:
            return vec2d(self.x*other, self.y*other)
    __rmul__ = __mul__
    
    def __imul__(self, other):
        if isinstance(other, vec2d):
            self.x *= other.x
            self.y *= other.y
        elif (hasattr(other, "__getitem__")):
            self.x *= other[0]
            self.y *= other[1]
        else:
            self.x *= other
            self.y *= other
        return self
 
    # Division
    def __div__(self, other):
        return self._o2(other, operator.div)
    def __rdiv__(self, other):
        return self._r_o2(other, operator.div)
    def __idiv__(self, other):
        return self._io(other, operator.div)
 
    def __floordiv__(self, other):
        return self._o2(other, operator.floordiv)
    def __rfloordiv__(self, other):
        return self._r_o2(other, operator.floordiv)
    def __ifloordiv__(self, other):
        return self._io(other, operator.floordiv)
 
    def __truediv__(self, other):
        return self._o2(other, operator.truediv)
    def __rtruediv__(self, other):
        return self._r_o2(other, operator.truediv)
    def __itruediv__(self, other):
        return self._io(other, operator.floordiv)
 
    # Modulo
    def __mod__(self, other):
        return self._o2(other, operator.mod)
    def __rmod__(self, other):
        return self._r_o2(other, operator.mod)
 
    def __divmod__(self, other):
        return self._o2(other, operator.divmod)
    def __rdivmod__(self, other):
        return self._r_o2(other, operator.divmod)
 
    # Exponentation
    def __pow__(self, other):
        return self._o2(other, operator.pow)
    def __rpow__(self, other):
        return self._r_o2(other, operator.pow)
 
    # Bitwise operators
    def __lshift__(self, other):
        return self._o2(other, operator.lshift)
    def __rlshift__(self, other):
        return self._r_o2(other, operator.lshift)
 
    def __rshift__(self, other):
        return self._o2(other, operator.rshift)
    def __rrshift__(self, other):
        return self._r_o2(other, operator.rshift)
 
    def __and__(self, other):
        return self._o2(other, operator.and_)
    __rand__ = __and__
 
    def __or__(self, other):
        return self._o2(other, operator.or_)
    __ror__ = __or__
 
    def __xor__(self, other):
        return self._o2(other, operator.xor)
    __rxor__ = __xor__
 
    # Unary operations
    def __neg__(self):
        return vec2d(operator.neg(self.x), operator.neg(self.y))
 
    def __pos__(self):
        return vec2d(operator.pos(self.x), operator.pos(self.y))
 
    def __abs__(self):
        return vec2d(abs(self.x), abs(self.y))
 
    def __invert__(self):
        return vec2d(-self.x, -self.y)
 
    # vectory functions
    def get_length_sqrd(self): 
        return self.x**2 + self.y**2
 
    def get_length(self):
        return math.sqrt(self.x**2 + self.y**2)    
    def __setlength(self, value):
        length = self.get_length()
        if length == 0:
            #print "division by zero in _setlength"
            pass # do nothing
        else:
            self.x *= value/length
            self.y *= value/length

    length = property(get_length, __setlength, None, "gets or sets the magnitude of the vector")
       
    def rotate(self, angle_degrees):
        radians = math.radians(angle_degrees)
        cos = math.cos(radians)
        sin = math.sin(radians)
        x = self.x*cos - self.y*sin
        y = self.x*sin + self.y*cos
        self.x = x
        self.y = y
 
    def rotated(self, angle_degrees):
        radians = math.radians(angle_degrees)
        cos = math.cos(radians)
        sin = math.sin(radians)
        x = self.x*cos - self.y*sin
        y = self.x*sin + self.y*cos
        return vec2d(x, y)
    
    def get_angle(self):
        if (self.get_length_sqrd() == 0):
            return 0
        return math.degrees(math.atan2(self.y, self.x))
    def __setangle(self, angle_degrees):
        self.x = self.length
        self.y = 0
        self.rotate(angle_degrees)
    angle = property(get_angle, __setangle, None, "gets or sets the angle of a vector")
 
    def get_angle_between(self, other):
        cross = self.x*other[1] - self.y*other[0]
        dot = self.x*other[0] + self.y*other[1]
        return math.degrees(math.atan2(cross, dot))
            
    def normalized(self):
        length = self.length
        if length != 0:
            return self/length
        return vec2d(self)
 
    def normalize_return_length(self):
        length = self.length
        if length != 0:
            self.x /= length
            self.y /= length
        return length
 
    def perpendicular(self):
        return vec2d(-self.y, self.x)
    
    def perpendicular_normal(self):
        length = self.length
        if length != 0:
            return vec2d(-self.y/length, self.x/length)
        return vec2d(self)
        
    def dot(self, other):
        return float(self.x*other[0] + self.y*other[1])
        
    def get_distance(self, other):
        return math.sqrt((self.x - other[0])**2 + (self.y - other[1])**2)
        
    def get_dist_sqrd(self, other):
        return (self.x - other[0])**2 + (self.y - other[1])**2
        
    def projection(self, other):
        other_length_sqrd = other[0]*other[0] + other[1]*other[1]
        projected_length_times_other_length = self.dot(other)
        return other*(projected_length_times_other_length/other_length_sqrd)
    
    def cross(self, other):
        return self.x*other[1] - self.y*other[0]
    
    def interpolate_to(self, other, range):
        return vec2d(self.x + (other[0] - self.x)*range, self.y + (other[1] - self.y)*range)
    
    def convert_to_basis(self, x_vector, y_vector):
        return vec2d(self.dot(x_vector)/x_vector.get_length_sqrd(), self.dot(y_vector)/y_vector.get_length_sqrd())
 
    def __getstate__(self):
        return [self.x, self.y]
        
    def __setstate__(self, dict):
        self.x, self.y = dict
        
# ---------------------------
# start


class Tank(pygame.sprite.Sprite):
    def __init__(self, screenrect, id="player1", mass=100.0):
        pygame.sprite.Sprite.__init__(self)
        #, color=(0,255,0) , pos=(100.0,100.0)
        self.screenrect = screenrect
        #self.mass = mass # how heavy the ship is
        self.mass = 100
        self.friction = 0.9 # 0.9 reduce speed for 10% each second
        if id == "player1":
            self.vc = (160,200)
            self.pos = vec2d(160,200)
            self.rotating=-30.0 # heading west
            self.color = (255,64,64)
            self.color2 = (255,0,128)
            self.color3 = (255,128,0)
            self.l = pygame.K_a
            self.r = pygame.K_d
            self.u = pygame.K_w
            self.d = pygame.K_s

        elif id == "player2":
            #self.rotating = 0.0 
            self.vc = (screenrect.width - 160, 200)
            self.pos = vec2d(screenrect.width - 160, 200)
            self.rotating=-150.0 # heading west
            self.color = (64,64,255)
            self.color2 = (0,128,255)
            self.color3 = (128,0,255)
            self.l = pygame.K_LEFT
            self.r = pygame.K_RIGHT
            self.u = pygame.K_UP
            self.d = pygame.K_DOWN
        elif id=="player3":
            self.vc = (160, screenrect.height - 200)
            self.pos = vec2d(160, screenrect.height - 200)
            self.rotating= 30.0 # heading west
            self.color = (64,255,64)
            self.color2 = (0,255,128)
            self.color3 = (128,255,0)
            self.l = pygame.K_j
            self.r = pygame.K_l
            self.u = pygame.K_i
            self.d = pygame.K_k
        elif id=="player4":
            self.vc = (screenrect.width - 160, screenrect.height - 200)
            self.pos = vec2d(screenrect.width - 160, screenrect.height - 200)
            self.rotating= 150.0 # heading west
            self.color = (64,64,64)
            self.color2 = (32,64,0)
            self.color3 = (10,64,32)
            self.l = pygame.K_KP4 
            self.r = pygame.K_KP6 
            self.u = pygame.K_KP8  # or KP8
            self.d = pygame.K_KP5
            
        self.wrap = True # wrap-around world
        self.force = 0
        #--- reloading and ammo
        self.reloading = 0.0 # tank can not fire while relaoding
        self.reloadingtime = 0.0 # seconds needed to reload, 0.0 means automatic fire
        self.ammowrap = 1 # how many time the ammo will wrap around world edge
        self.moving = vec2d(0.0,0.0)
        self.image1 = pygame.Surface((50,50))
        self.image1.fill((255,255,255))         # fill with white
        self.image1.set_colorkey((255,255,255)) # make white transparent
        pygame.draw.rect(self.image1 , (10,10,10), (0,0,50,8))
        pygame.draw.rect(self.image1, (10,10,10), (0,42,50,50))
        self.p1 = (-25.0,-25.0) # middle is 25,25
        self.p2 = (-25.0, 25.0) # middle is 25,25
        pygame.draw.polygon(self.image1, (64,64,64), [(5,10),(5,40),(50,25)],0)
        pygame.draw.circle(self.image1, self.color,(25,25),16,0) # 0 fllt den Kreis
        self.image1.convert_alpha()
        self.image = self.image1.copy() # copy to not destroy image1
        self.rect = self.image.get_rect()
        self.rect.center = (round(self.pos.x,0),round(self.pos.y,0)) 
        self.limit = 500 # the speed limit
        self.rotspeed = 0.0
        self.maxrotspeed =300 # maximum turnspeed
        self.rotdelta = 30   # um wieviel gedreht wird
        self.forcedelta = 5  # 
        self.oldcenter = (0,0)
        self.oldcenter2 = (0,0)
        self.oldrot = 0
        self.spacemove= vec2d(0,0)
        self.newmoving = vec2d(0,0)
        self.cm = 0.0 # angle to mouse
        self.cmd = 0.0 # distance to mouse
        self.showvector = True
        self.modus = "space"
        self.speedflag = False
        self.showtext = False
        self.drawTracer = False
        self.id= id
        self.hitpoints = 500.0  # float division ! # 500.0
        self.hitpointsfull = 500.0       # 500.0
        self.peaceful = False
        self.hitradius = 20.0
        self.damagemax = 20 # how much damage a bullet in the center does
        # damagemax can be higher by 5 because it is difficult to
        # teleport a bullet into the center
        self.damagemin = 1  # how much damage a bullet on the edge does
        self.offset = 15 # if set to 0 tank can complete disappear behind
                        # screen edge bevor wrap-around on other site
                        # a offset > 0 spoil that, so that a bit of the tank
                        # should be always visible
        self.shotby = None
        self.shots = 0 # how many balls this tank shoots in his lifetime
        self.hits = 0 # how many times this thank hits an enemy in his lifetime
        
        
    def fire(self):
        """check if firing is allowed, return True if yes and set the reloadingtime"""
        if self.peaceful:
            return False
        elif self.reloading > 0:
            return False # Tank is still reloading
        elif not self.screenrect.collidepoint(self.rect.center):
            # firing not allowed if Tank center out of screenrect
            return False
        else:
            self.reloading = self.reloadingtime # now the weapon must be reloaded for some time
            self.shots += 1
            return True
        
    def update(self, tick_seconds):
        """tick is the time passed since last frame in seconds"""
        #save old position
        self.rect = self.image.get_rect()
        self.oldcenter = self.rect.center # from the image, only for rotating
        
        # check reloading time,check if ready to fire again
        if self.reloading: # <>0..True, 0..False
            self.reloading -= tick_seconds
        if self.reloading < 0:
            self.reloading = 0
        
        # image selector / rotation / speed lights painting
        self.image = self.image1.copy()
        if self.rotspeed < 0:
            #self.image = self.image2
            pygame.draw.rect(self.image,  (255,0,0), (0,0,8,8))
            pygame.draw.rect(self.image,  (255,0,0), (42,42,50,50))
        elif self.rotspeed > 0:
            pygame.draw.rect(self.image, (255,0,0), (0,42,8,50))
            pygame.draw.rect(self.image, (255,0,0), (42,0,50,8))           
        if self.force > 0:
            pygame.draw.rect(self.image, (255,0,0), (0,10,5,30))
        elif self.force < 0:
            pygame.draw.rect(self.image, (255,0,0), (45,10,50,30))
        

        #--- rotate the sprite
        self.rot(self.image)
        
        #--- calculate new position
        self.rect.center = (round(self.pos.x,0), round(self.pos.y,0))
        #self.oldcenter2 = self.rect.center # save for drawing

        #--- render mousevector  # FIXME...ugly !
        c = vec2d(self.rect.center) # vector to center on screen
        m = vec2d(pygame.mouse.get_pos()) #vector to mousepos on screen
        cm =  m - c # vector from sprite-center to mousepos
        self.cm = cm.angle
        self.cmd = cm.length 
        cm.length = 16 # shrink length to radius of sprite circle
        #    calulate the new middle of the rotated sprite
        nm = vec2d(self.image.get_rect().width/2,self.image.get_rect().height/2)
        cm += nm  # correction because sprite is rotated, middle point moves
        pygame.draw.line(self.image, (0,0,0), (nm.x,nm.y), (int(cm.x), int(cm.y)),1)

        # more precise keyboard event handler
        pressed_keys = pygame.key.get_pressed()
        if pressed_keys[self.l]:
            self.rotspeed += self.rotdelta 
        if pressed_keys[self.r]:
            self.rotspeed -= self.rotdelta
        if pressed_keys[self.u]:
            self.force += self.forcedelta
        if pressed_keys[self.d]:
            self.force -= self.forcedelta
            
        # halt rotation when not-auto
        if self.modus != "auto":
            if (not pressed_keys[self.l] and 
                not pressed_keys[self.r]):
                    self.rotspeed = 0 # stop rotation
            if (not pressed_keys[self.u] and
                not pressed_keys[self.d]):
                    self.force = 0 # stop moving
            
        #limit to limit, maxrotspeed
        if self.rotspeed > self.maxrotspeed:
            self.rotspeed = self.maxrotspeed
        if self.rotspeed < -self.maxrotspeed:
            self.rotspeed = -self.maxrotspeed
        
        if self.force >= self.limit:
            self.force = self.limit
            self.speedflag = True
        elif self.force <= -self.limit:
            self.force = -self.limit
            self.speedflag = True
        else:
            self.speedflag = False
            
        #reset rotation on 360 Degree
        if self.rotating < -360:
            self.rotating += 360
        if self.rotating > 360:
            self.rotating -= 360
        
        # time-based rotation        
        self.rotating += self.rotspeed * tick_seconds 
        
        #FIXME: das geht sicher einfacher auch
        # simple forward movement
        if self.modus=="space":
            if self.force!=0:
                if self.rotating != 0:
                    dazu = vec2d(self.force, 0)
                    dazu.rotate(-self.rotating)
                    #print self.spacemove,  self.force, -self.rotating, dazu                    
                    self.spacemove += dazu
                else:
                    self.spacemove += vec2d(self.force,0)
            # check speed limit
            if self.spacemove.length >= self.limit:
                self.spacemove.length = self.limit
                self.speedflag = True
            else:
                self.speedflag = False
            #self.pos += self.spacemove * tick_seconds
            self.newmoving = self.spacemove # komaptibel machen ?
            
        else:
            if self.force!= 0:
                self.newmoving = vec2d(self.force,0)
                if self.rotating != 0:
                    self.newmoving.rotate(-self.rotating)
                #self.pos += self.newmoving * tick_seconds
        self.newmoving *= self.friction ** tick_seconds # Reibung Leo
        self.pos += self.newmoving * tick_seconds 
        if self.wrap: 
            # wrap-around world
            if self.pos.x + self.rect.width/2 < 0:
                #self.pos.x = self.screenrect.get_width()  + self.rect.width/2
                self.pos.x = self.screenrect.width  + self.rect.width/2 - self.offset
            if self.pos.x - self.rect.width/2 > self.screenrect.width:
                self.pos.x = 0 - self.rect.width/2 + self.offset
            if self.pos.y + self.rect.height/2 < 0:
                self.pos.y = self.screenrect.height + self.rect.height/2 - self.offset
            if self.pos.y - self.rect.height/2 > self.screenrect.height:
                self.pos.y = 0 - self.rect.height/2 + self.offset
        else:
             #no wrap-around  , stop on end of screen
            if self.pos.x < 0:
                self.pos.x = 0 
            if self.pos.x > self.screenrect.width:
                self.pos.x = self.screenrect.width
            if self.pos.y < 0:
                self.pos.y = 0
            if self.pos.y > self.screenrect.height:
                self.pos.y = self.screenrect.height
        
        #draw tracer ?
        if self.drawTracer:
            self.tracer()
        #else:
        #    self.dirtyrect=(0,0,0,0)
        
    def tracer(self):  
        #test if tracer is not too long (because world-wrap)
        nc = vec2d(self.rect.center)
        oc = vec2d(self.oldcenter2)
        if (nc - oc).length < self.rect.width:
            pygame.draw.line(background, self.color,self.oldcenter2, self.rect.center,2)
            nc1 = vec2d(self.p1)
            nc2 = vec2d(self.p2)
            oc1 = vec2d(self.p1)
            oc2 = vec2d(self.p2)
            # rotate the tracer-vectors
            vec2d.rotate(nc1,-self.rotating)
            vec2d.rotate(nc2,-self.rotating)
            vec2d.rotate(oc1,-self.rotating)
            vec2d.rotate(oc2,-self.rotating)
            #"----adding rect center----"
            nc1 += nc 
            nc2 += nc
            #"------ adding oldcenter ------"
            oc1 += oc
            oc2 += oc
            # draw the lines from old to new
            pygame.draw.line(background, self.color2, (oc1.x, oc1.y),(nc1.x,nc1.y),1)
            pygame.draw.line(background, self.color3, (oc2.x, oc2.y),(nc2.x,nc2.y),1)
            #self.dirtyrect =(int(min(nc1.x, nc2.x, oc1.x, oc2.x, oc.x, nc.x))-1,
            #                 int(min(nc1.y, nc2.y, oc1.y, oc2.y, oc.y, nc.y))-1,
            #                 int(max(nc1.x, nc2.x, oc1.x, oc2.x, oc.x, nc.x))+1,
            #                 int(max(nc1.y, nc2.y, oc1.y, oc2.y, oc.y, nc.y))+1)
        self.oldcenter2 = self.rect.center # save old tracerposition        
                                        
    def rot(self, image):
        self.image = pygame.transform.rotate(image, self.rotating)
        self.rect.center = self.oldcenter    
    
class Bar(pygame.sprite.Sprite):
        """ a health-bar floating above each player"""
        
        def __init__(self, boss, vectorbar=False, color=(0,255,0)):
            pygame.sprite.Sprite.__init__(self)
            self.vectorbar = vectorbar
            self.boss = boss
            if self.vectorbar:
                self.long = 300 # vectorsprite circle radius * 2
                #print "dreihundert"
            else:
                self.long = boss.rect.width
            self.longold = self.long
            self.percent = 1.0
            self.percentold = 0.0
            self.color = color
            self.image = pygame.Surface((self.long,5))
            
        def update(self, tick):
            """tick is the time passed since last frame in seconds"""
            if self.boss.hitpoints <= 0:
                self.kill()
            self.percent = (self.boss.hitpoints /
                            self.boss.hitpointsfull)
            #print self.boss_sprite.hitpoints, self.boss_sprite.hitpointsfull, self.percent
            if not self.vectorbar:
                self.long = self.boss.rect.width
            if self.percent != self.percentold or self.longold != self.long:
                #print self.percent, self.percentold, self.long, self.longold
                self.image = pygame.Surface((self.long,5))
                self.rect = self.image.get_rect()
                self.image.fill((255,255,255))        # white
                pygame.draw.rect(self.image,(0,255,0),(0,0,
                                 int(self.long*self.percent), 5))
                #black rectangle
                pygame.draw.rect(self.image,(0,0,0),(0,0,self.long,5), 1) 
                self.image.set_colorkey((255,255,255))
                self.image.convert_alpha()
            if self.vectorbar:
                self.rect.centerx = self.boss.vc[0]
                self.rect.centery = self.boss.vc[1] - 160 # vectorbar above vectorcircle
            else:
                self.rect.centerx = self.boss.rect.centerx
                self.rect.centery = self.boss.rect.y - 10
            self.percentold = self.percent
            self.longold = self.long

class Text(pygame.sprite.Sprite):
        """a changable text"""
        def __init__(self, pos, msg="Hello World",color=(5,5,5), maxlifetime=-1.0, textsize=25, vec=vec2d(0,0),msgchange=False, zoom=False):
            """ negative maxlifetime means stay until Game Over
                msgchange means the message may change over time
                pos in format(x,y), will be changed into vec2d in Text__init__"""
            pygame.sprite.Sprite.__init__(self)
            #self.static = static #static means text does not disappear
            self.zoom = zoom
            self.zoomfactor = 4.0
            self.textsize = int(textsize)
            self.textsize0 = self.textsize
            #print type(self.textsize), self.textsize
            self.msgchange = msgchange
            self.vec = vec
            self.pos = vec2d(pos)
            self.msg = msg
            self.color = color
            self.recalcimage()
            self.rect.center = pos
            self.lifetime = 0
            self.maxlifetime = maxlifetime #seconds
            self.tick = 0.0 # seconds since last frame
            #self.recalc(self.msg)

        
        def update(self, tick):
            """tick is passed seconds"""
            self.tick = tick
            self.lifetime += tick
            if self.zoom:
                self.textsize = int(self.textsize0 + self.lifetime * self.zoomfactor) # int instead of round becaouse round makes float and float upset pygame.font
                self.msgchange = True
            if self.msgchange:
                self.recalcimage()
            if self.vec != vec2d(0,0):
                self.pos += self.vec * self.tick # self.pos is a vec2d object
                self.rect.center  = (round(self.pos.x,0), round(self.pos.y,0))
            if self.maxlifetime > 0 and self.lifetime > self.maxlifetime:
                self.kill()
        
        #def kill(self):
        #    pygame.sprite.Sprite.kill(self)
            
        def recalcimage(self):
            """renders the text to self.image"""
            self.font = pygame.font.SysFont("None",self.textsize)
            self.textsurface1 = self.font.render(self.msg, True, self.color) #antialias = False
            self.image = pygame.Surface((self.textsurface1.get_size()))
            self.image.fill((255,255,255))         # fill with white
            self.image.set_colorkey((255,255,255)) # make white transparent
            #self.image = self.image1.copy() # to save image1
            self.image.blit(self.textsurface1,(0,0))
            self.rect = self.image.get_rect()
            self.rect.center  = (round(self.pos.x,0), round(self.pos.y,0))
     


class HitpointText(Text):
    """ this class inherit from Text class and updated the hitpoints of a given player"""
    def __init__(self, boss):
        Text.__init__(self, boss.vc , "dummytext", (0,0,0),-1,20, vec2d(0,0), True, False)
        self.boss = boss
        #print self.boss, self.pos
        self.pos += vec2d(0,-170) # self.pos is a vec2d object from Text ?
    def update(self, tick):
        self.msg = "Hitpoints:"+str(self.boss.hitpoints)
        Text.update(self, tick)




        
        
class VectorSprite(pygame.sprite.Sprite):
    """draws a drawing of the tank in a fixed position
       including vectors for relative speed, enemy etc."""
    def __init__(self, boss):
        pygame.sprite.Sprite.__init__(self)
        self.boss = boss
        #self.startx = startx
        self.image0 = pygame.Surface((300,300)) # 200,200
        self.image0.fill((255,255,255))         # fill with white
        self.image0.set_colorkey((255,255,255)) # make white transparent
        self.image0.convert_alpha()
        self.vc = (int(self.boss.vc[0]),int(self.boss.vc[1])) # Vectorcenter from boss_sprite
        #print "self.vc", self.vc
        self.color = self.boss.color # get color from boss
        # draw polygon, same as Tank, but without colors
        self.image1 = pygame.Surface((50,50))
        self.image1.fill((255,255,255))         # fill with white
        self.image1.set_colorkey((255,255,255)) # make white transparent
        pygame.draw.rect(self.image1 , self.color, (0,0,50,8),1)
        pygame.draw.rect(self.image1 , self.color, (0,42,50,8),1) # small bug
        pygame.draw.polygon(self.image1, self.color, [(0,10),(0,40),(50,25)],1)
        pygame.draw.circle(self.image1, self.color,(25,25),16,1) # 0 fllt den Kreis
        pygame.draw.line(self.image1, self.color,(25,25),(50,25),1) # strich schaut nach rechts
        self.image1.convert_alpha()
        self.image = self.image0.copy() # to save image1
        self.rect = self.image.get_rect()
        self.size = 5
        self.dangerlist = []
        self.enemylist = []

    def learn(self, enemy, danger=True):
        """ learn about one enemy at a time, but not about self"""
        if danger:
            self.dangerlist.append(enemy)
        else:
            if enemy.color != self.boss.color:
                self.enemylist.append(enemy)
           
    
    def update(self, tick_seconds):
        """ update the vectors and rotation of the tank.
            tick_seconds is only here to get accepted, but i do nothing with it"""
        #self.dangerlist = []
        #self.enemylist = []
        if self.boss.showvector:
            #--- draw vectorsprite with correct rotation
            self.image = self.image0.copy()
            self.image2 = self.image1.copy()
            self.image2 = pygame.transform.rotate(self.image2 , self.boss.rotating)
            rect = self.image2.get_rect()
            center2 = rect.center
            #self.image.blit(self.image2, (100-rect.width/2, 100-rect.height/2))
            self.image.blit(self.image2, (150-rect.width/2, 150-rect.height/2))
            self.rect.center = self.vc
            
            #--- draw big mousevector
            cm = vec2d(0,min(150, self.boss.cmd)) # cmd is sprite-mousedistance
            cm.rotate(self.boss.cm-90) # self.boss.cm contains the angle from tank to mouse
            cm += vec2d(self.vc)
            pygame.draw.line(screen, (0,255,255),(self.vc), (cm.x, cm.y),1) # cyan
            
            #--- draw force vector
            f = 1.0 * self.boss.force / self.boss.limit # 1.5 is around the vectorcircle 
            cm = vec2d(0, f*150.0)
            cm.rotate(-self.boss.rotating-90)
            cm += vec2d(self.vc)
            pygame.draw.line(screen, self.boss.color, (self.vc), (round(cm.x,0), round(cm.y,0)),20)
            
            
            #--- draw space vector
            if self.boss.modus =="space":
                speed = 1.0 * self.boss.spacemove.length / self.boss.limit
                s = min(1, speed)
                if speed > 1:
                    self.size +=1
                else:
                    self.size = 5
                cm = vec2d(0, s*150.0)
                cm.rotate(self.boss.spacemove.angle-90)
                cm += vec2d(self.vc)
                pygame.draw.line(screen, (255,0,255), (self.vc), (int(cm.x), int(cm.y)),self.size) # pink
            
            #--- draw sprite vector
            cm =  vec2d(self.boss.rect.center) - vec2d(self.vc)  
            #diagonal = vec2d(self.vc) - vec2d(self.boss.screenrect.width, self.boss.screenrect.height)
            #dia = diagonal.length * 1.0 # to get float
            #cm.length = (cm.length / dia)*100
            cm.length = min(cm.length, 150.0)  #100
            cm+=vec2d(self.vc)
            #print diagonal, cm, cm.length 
            pygame.draw.line(screen, (0,0,0), (self.vc), (int(cm.x), int(cm.y)),1)
                        
            #--- draw dangervector
            for dang in self.dangerlist:
                #print dang
                size = 1
                cd = dang.pos - self.boss.pos
                cd.length = min(cd.length, 150.0)
                if cd.length < 150:
                    size = int(150 - cd.length)
                cd+=vec2d(self.vc)
                #print (int(cd.x), int(cd.y))
                pygame.draw.line(screen, (255,255,0), (self.vc), (int(cd.x), int(cd.y)),size)
            self.dangerlist = []
            
            #--- draw enemyvector
            for enemy in self.enemylist:
                size = 1
                cd = enemy.pos - self.boss.pos
                cd.length = min(cd.length, 150.0)
                if cd.length < 150:
                    size = int(150 - cd.length)
                cd+=vec2d(self.vc)
                pygame.draw.line(screen, enemy.color, (self.vc), (int(cd.x), int(cd.y)),size)
            self.enemylist = []
            
        else:
            self.rect.center = (-400,-400) # hide vectorsprite out of screenrect


        
class Ball(pygame.sprite.Sprite):
    def __init__(self, bossSprite, smoke=False, mass=1):
        pygame.sprite.Sprite.__init__(self)
        self.boss = bossSprite
        self.image = pygame.Surface((10,10))
        self.image.fill((255,255,255))         # fill with white
        self.image.set_colorkey((255,255,255)) # make white transparent
        pygame.draw.circle( self.image,self.boss.color, (5,5), 5 , 0)
        self.image.convert_alpha()
        self.rect = self.image.get_rect()
        self.pos = vec2d(self.boss.rect.center)
        self.rect.center = (round(self.pos.x,0), round(self.pos.y,0))
        self.moving=vec2d(self.boss.limit * 1.1,0) # speeed of bullet = 110% of max speed of player 
        #self.moving.rotate(self.boss.cm) # shoot to mousepointer
        self.moving.rotate(-self.boss.rotating) # shoot to direction of Tank/Ship
        self.moving += self.boss.spacemove # add tank velocity to ball velocity
        self.massfactor = 0.2 # reduces the impact in relation to a players mass. #.91 a bissl gross
        self.ammowrap = self.boss.ammowrap # how many times bullet can wrap around screen edge

    def update(self, tick_seconds):
        '''tick is time passed in seconds'''
        #print self.pos, self.moving, tick_seconds
        self.pos += self.moving * tick_seconds
        self.rect.center = (round(self.pos.x,0), round(self.pos.y,0))
        if not self.boss.screenrect.collidepoint(self.rect.center):
            if self.ammowrap > 0:
                self.ammowrap -=1 # one less time allowed to wrap world
                if self.pos.x > self.boss.screenrect.width:
                    self.pos.x = 0
                if self.pos.x < 0:
                    self.pos.x = self.boss.screenrect.width
                if self.pos.y > self.boss.screenrect.height:
                    self.pos.y = 0
                if self.pos.y < 0:
                    self.pos.y= self.boss.screenrect.height
            else:
                self.kill()
        
class Danger(pygame.sprite.Sprite):
    def __init__(self, screenrect, start="top", size=50  ):
        pygame.sprite.Sprite.__init__(self)
        self.screenrect = screenrect
        self.size = size
        self.image = pygame.Surface((self.size,self.size))
        #print start
        if start == "top":
            self.pos = vec2d(random.randrange(0,screenrect.width),random.randrange(0,self.size))
            self.vec = vec2d(random.randrange(5,100) * random.choice([-1,1]), 0)
        elif start == "bottom":
            self.pos = vec2d(random.randrange(0,screenrect.width),screenrect.height - random.randrange(0,self.size))
            self.vec = vec2d(random.randrange(5,100) * random.choice([-1,1]), 0)
        elif start == "left":
            self.pos = vec2d(random.randrange(0,self.size), random.randrange(0,screenrect.height))
            self.vec = vec2d(0,random.randrange(5,100) * random.choice([-1,1]))
        elif start == "right":
            self.pos = vec2d(screenrect.width - random.randrange(0,self.size), random.randrange(0,screenrect.height))
            self.vec = vec2d(0,random.randrange(5,100) * random.choice([-1,1]))
        
        #self.image.convert_alpha()
        self.rect = self.image.get_rect()
        #self.pos =  vec2d(10,20)
        self.rect.center=  (round(self.pos.x,0), round(self.pos.y,0))
        #self.moving = vec2d(22,0)
    
    def update(self, tick_seconds):
        '''tick is time passed in seconds'''
        #print self.pos, self.moving, tick_seconds
        self.color = (255,random.randint(128,255),0) # between yellow and red ?
        pygame.draw.rect( self.image,self.color, (0,0,self.size,self.size), 0)
        self.pos += self.vec * tick_seconds
        self.rect.center = (round(self.pos.x,0), round(self.pos.y,0))
        if not self.screenrect.collidepoint(self.rect.center):
            self.vec *= -1

class Wound(pygame.sprite.Sprite):
        """ a little explosion marking the 'wound' of a hit"""
        def __init__(self, pos, size, maxlifetime=0.5, boss_sprite=None):
            pygame.sprite.Sprite.__init__(self)
            self.size = int(size) # sometimes, wound comes as float (from tux?)
            #if self.size < medium:
            #    self.size *=2
            
            self.pos = pos
            self.maxlifetime = maxlifetime # in seconds
            self.boss_sprite = boss_sprite
            self.age = 0 # age in decimal seconds
            self.frames = 0 #frames in integer
            self.image = pygame.Surface((size*2, size*2))
            self.surface_center = (self.size, self.size) 
            self.rect = self.image.get_rect()
            self.rect.center = (round(self.pos.x,0),round(self.pos.y,0))
            #if self.boss_sprite:
                #print self.boss_sprite.rect.centerx, self.boss_sprite.rect.centery
            #    self.dx = self.pos[0] - self.boss_sprite.rect.centerx 
            #    self.dy = self.pos[1] - self.boss_sprite.rect.centery
            self.update(0) # update need the argument tick
            
        def update(self, tick_seconds):
            """ tick_seconds is decimalseconds passed since last frame"""
            self.age += tick_seconds
            self.frames +=1
            if self.age > self.maxlifetime: #one second at 30 fps
                self.kill()
            else:
                self.rect.center = (round(self.pos.x, 0), round(self.pos.y,0))
                pygame.draw.circle(self.image, (255,random.randint(0,255),0),
                     self.surface_center,min(self.size,self.frames), 0)
                self.image.set_colorkey((0,0,0))
                self.image.convert_alpha()
                #if self.boss_sprite:
                #    self.rect.centerx = self.boss_sprite.rect.centerx + self.dx
                #    self.rect.centery = self.boss_sprite.rect.centery + self.dy
                #else:
                #    self.rect.center = self.pos
                



def paint(x, y,  color):
    pygame.draw.circle(background, color, (x,y), 150, 1)
    pygame.draw.line(background, color, (x-160, y) , (x+160,y), 1)
    pygame.draw.line(background, color, (x,y-160), (x,y+160),1)
    textsurface = myFont.render(u"0 = 360", True, color)
    background.blit(textsurface, (x+50,y-20))
    textsurface = myFont.render(u"90", True, color)
    background.blit(textsurface, (x-10,y-150))
    textsurface = myFont.render(u"180", True, color)
    background.blit(textsurface, (x-140,y-20))
    textsurface = myFont.render(u"270", True, color)
    background.blit(textsurface, (x-10,y+125))
    
#--- main start  --
pygame.init()
screen=pygame.display.set_mode((0,0)) # (0,0) uses the full screensize
screenrect = screen.get_rect()
pygame.display.set_caption("press Esc to exit")
#--- background
background = pygame.Surface(screen.get_size())
#background = background.convert()
background.fill((255,255,255))     #fill the background white
#a bit of text
myFont = pygame.font.SysFont("None",25)
#textsurface = myFont.render("Player1: F1=modus, w,as,d,cursor=move, space=shoot", True, (0,0,255))
textsurface0 = myFont.render("pres ESC to Quit", True, (0,0,0))
textsurface1 = myFont.render("Player1: w,a,s,d", True, (0,0,0))
#textsurface2 = myFont.render("Player2: F12=modus, j,i,l,k, Numpad=move, RCTRl,NUM_Enter=shoot", True, (0,0,255))
textsurface2 = myFont.render("Player2: j,i,l,k", True, (0,0,0))
textsurface3 = myFont.render("Player3: cursor-keys", True, (0,0,0))
textsurface4 = myFont.render("Player4: Numpad 4,8,5,6", True, (0,0,0))
#background.blit(textsurface, (20,410)) # blit the textsurface on the backgroundsurface
#background.blit(textsurface2, (20, 430))
#background.blit(textsurface3, (20, 450))
# red circle with crosshair

paint(160, 200, (255,32,32)) # player1, red, left upper corner
paint(screenrect.width - 160, 200, (32,32,255)) # player2, blue right upper corner
paint(160, screenrect.height - 200 , (32,255,32)) # player3, green, lower left corner
paint(screenrect.width - 160, screenrect.height - 200 , (32,32,32)) # player4, black, lower right corner

background.blit(textsurface1, (screenrect.width/2-40,50))
background.blit(textsurface2, (screenrect.width/2-40,70))
background.blit(textsurface3, (screenrect.width/2-40,90))
background.blit(textsurface4, (screenrect.width/2-40,110))
background.blit(textsurface0, (screenrect.width/2-40,130))

backgroundnew = background.copy()
screen.blit(background, (0,0)) # blit the  backgroundsurface on the screen

#--- sprite groups
vectorgroup = pygame.sprite.Group()
ballgroup = pygame.sprite.Group()
tankgroup = pygame.sprite.Group()
bargroup = pygame.sprite.Group()
dangergroup = pygame.sprite.Group()
woundgroup = pygame.sprite.Group()
textgroup = pygame.sprite.Group()
# create some sprites
#--- player1 
player1 = Tank(screenrect,"player1") #red
player1vector = VectorSprite(player1)
textgroup.add( HitpointText(player1)  )
#--- player2
player2 = Tank(screenrect,"player2") # blue
player2vector = VectorSprite(player2)
textgroup.add( HitpointText(player2)  )
#-- player3
player3 = Tank(screenrect, "player3") # green
player3vector = VectorSprite(player3)
textgroup.add( HitpointText(player3))
#-- player4
player4 = Tank(screenrect, "player4") # green
player4vector = VectorSprite(player4)
textgroup.add( HitpointText(player4))



# put the sprites in the correct group
bargroup.add(Bar(player1), Bar(player1, True),
             Bar(player2), Bar(player2, True),
             Bar(player3), Bar(player3, True),
             Bar(player4), Bar(player4, True), )

tankgroup.add(player1, player2, player3, player4)
#stuffgroup.add(player1text, player1speedtext, player1vector,  player2text, player2speedtext, player2vector)
vectorgroup.add(player1vector, player2vector, player3vector, player4vector)
dangergroup.add( Danger(screenrect, "top"),
                 Danger(screenrect, "bottom"),
                 Danger(screenrect, "left"),
                 Danger(screenrect, "right"))
#allgroup = pygame.sprite.LayeredUpdates(playervector, playertext, speedtext, player, ballgroup)
allgroup = pygame.sprite.LayeredUpdates(vectorgroup,  dangergroup, woundgroup, textgroup, bargroup, ballgroup, tankgroup)



#--- loop prepare ---
mainloop = True
#clock = pygame.time.Clock()
fps = 60 #frames per second
seconds_played = 0.0
recalc = False # recalculate the sprite groups reset to False
finale = False # draw the game-over scene (final explosion etc.)
startGameOverMsg = False
#--- mainloop ------
while mainloop:
    tick_time = pygame.time.Clock().tick(fps) # milliseconds since last frame
    tick_seconds = tick_time / 1000.0 # decimal-seconds since last frame
    seconds_played += tick_seconds # counter, will not be resetted    
    #clock.tick(30)
    #event handler
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            mainloop = False
        elif event.type == pygame.KEYDOWN:
            # Toggle keys better with keydown than with pressed_keys
            #--- Esc quit -------------
            if event.key == pygame.K_ESCAPE:
                mainloop = False
   
               
            #--- clean F5 -------------
            if event.key == pygame.K_F5:    
                background = backgroundnew.copy()
                screen.blit(background, (0,0)) # redraw the background
            #---tracer F6 -----------------    
            if event.key == pygame.K_F6:
                for tank in tankgroup:
                    tank.drawTracer = not tank.drawTracer          

    #--- fire 
    for tank in tankgroup:
        if tank.fire():
            ballgroup.add(Ball(tank))
            recalc = True        
        
    #--- mainloop core -----------                  
    #--- clear the sprites
    allgroup.clear(screen, background)
     
    if recalc:
        # it is very important that this lines comes AFTER allgroup.clear!
        # else there will be ugly uncleaned sprites all around
        # allgroup = pygame.sprite.LayeredUpdates(stuffgroup,  woundgroup, textgroup, dangergroup, bargroup, tankgroup, ballgroup)
        allgroup = pygame.sprite.LayeredUpdates(vectorgroup,  dangergroup, woundgroup, textgroup, bargroup, ballgroup, tankgroup)
    recalc = False # reset recalc
    #--- update all sprites
    allgroup.update(tick_seconds)
    #--- feed sprite-position to vectorgroup
    for vsprite in vectorgroup:
        for dang in dangergroup:
            vsprite.learn(dang, True)
        for tank in tankgroup:
            #print tank
            vsprite.learn(tank, False)
       
    #--- collision detection
    # --- collision with tank and ball ?
    for tank in tankgroup:
        crashgroup = pygame.sprite.spritecollide(tank, ballgroup, False)
        for ball in crashgroup:
            if ball.boss == tank: # friendly fire
               #print "friendly fire"
               pass                #do nothing
            else:
               distance1 = vec2d(tank.pos) #calculate distance to tank center
               distance2 = vec2d(ball.pos)
               distance = distance1 - distance2
               if distance.length > tank.hitradius:
                    pass # nothing happened, bullet missed tank
               else:
                   tank.shotby =  ball.boss.id
                   ball.boss.hits += 1 # one point for the shooter
                   damage = tank.damagemin + ((tank.hitradius - distance.length ) / tank.hitradius ) * (tank.damagemax - tank.damagemin)
                   damage = int(damage)
                   # draw damage text in vectorsprite center (160,200) or (-160,200)
                   textgroup.add(Text(vec2d(tank.vc), str(damage), ball.boss.color, 1.5, 25, 
                                      vec2d(random.randint(-90,90),random.randint(-250,-120)),
                                      False, True )) # vc = vectorcenter
                   tank.hitpoints -= damage 
                   
                   tank.spacemove += ball.moving * ball.massfactor
                   woundgroup.add(Wound(ball.pos, 5))
                   recalc = True
                   ball.kill()
    
    # -- collision with danger ?
    for tank in tankgroup:
        crashgroup = pygame.sprite.spritecollide(tank, dangergroup, False)
        for dangerzone in crashgroup:
            damage = 1
            textgroup.add(Text(vec2d(tank.vc), str(damage), (200,200,0), 1.5, 25, 
                              vec2d(random.randint(-90,90),random.randint(-250,-120)),
                              False, True )) # vc = vectorcenter
            tank.hitpoints -= damage
            
            
    #-- collision between ball and danger:
    for dang in dangergroup:
        crashgroup = pygame.sprite.spritecollide(dang, ballgroup, True)
        #remove ball if ball hits danger
        #TODO: do something with danger, like add movement etc ?
            
    # -- collision with other player ?
    for tank in tankgroup:
        tankgroup2 = tankgroup.copy() # copy of tankgroup, include self
        tankgroup2.remove(tank) # remove self of group
        crashgroup = pygame.sprite.spritecollide(tank, tankgroup2, False)
        for tank2 in crashgroup:
            #FIXME --- bis mir was bessers einfllt
            tank.hitpoints -= 1
            textgroup.add(Text(vec2d(tank.vc), str(1), tank2.color, 1.5, 25, 
                  vec2d(random.randint(-90,90),random.randint(120,240)),
                  False, True )) # tank-collision: damage text floats DOWN instead up
            
            
    #--- game over ?  
    for tank in tankgroup:
        if tank.hitpoints < 0:
            woundgroup.add(Wound(tank.pos, 100, 2)) # final explosion
            tank.peaceful = True # dead Tank cannot shoot
            if len(tankgroup) > 1:
                textgroup.add(Text(tank.pos, "Loser", tank.color, 5.0, 72, vec2d(0,0), False, True))
                textgroup.add(Text(tank.vc, "Loser", (0,0,0), -1, 48, vec2d(0,0), False, False))
                textgroup.add(Text(tank.vc+ vec2d(0,25), "Rank: %i " % len(tankgroup), (0,0,0), -1, 48, vec2d(0,0), False, False))
                textgroup.add(Text(tank.vc+ vec2d(0,50), "hit ratio: %f" % (tank.shots / tank.hits))) # future division, result in float
                tank.showvector = False
            tank.kill()
    if len(tankgroup) == 1 and not startGameOverMsg:
        startGameOverMsg = True
        for tank in tankgroup:
            textgroup.add(Text(tank.pos, "Victory", tank.color, 5.0, 72, vec2d(0,0), False, True))
            textgroup.add(Text(tank.vc, "Winner", (0,0,0), -1, 48, vec2d(0,0), False, False))
            textgroup.add(Text(tank.vc+ vec2d(0,25), "Rank: %i " % len(tankgroup), (0,0,0), -1, 48, vec2d(0,0), False, False))
            textgroup.add(Text(tank.vc+ vec2d(0,50), "hit ratio: %f" % (tank.shots / tank.hits))) # future division, result in float
        textgroup.add(Text((screenrect.width/2,screenrect.height/2), "Game Over", (1,1,1), 5.0,100, vec2d(0,-20), False, True))
        finale = True
            
                         
    if finale:
        if len(woundgroup) == 0:
            mainloop = False # leave game
                                
    #--- draw the sprites
    allgroup.draw(screen)
    #--- decorate screen
    #pygame.display.set_caption("player1 [F1]: %s player2 [F12]: %s mouse: %s balls: %i "
    #% (player.modus, p2.modus , pygame.mouse.get_pos(),len(ballgroup)))
    pygame.display.set_caption( "# text: %i, # balls: %i " % (len(textgroup), len(ballgroup)))
    pygame.display.flip()          # flip the screen 30 times a second
#--- end of loop
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.