#!/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
|