Da ich noch nicht viel Erfahrung mit Python habe würde ich mich über Feedback natürlich sehr freuen.
Aber nun zum Code:
Code: Alles auswählen
#!/usr/bin/env python
"""Pong implemented in python/pygame"""
import sys
import time
import math
import pygame
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
class Rect(object):
"""Represents a rectangle"""
def __init__(self, left, top, width, height):
self.left = left
self.top = top
self.width = width
self.height = height
def get_right(self):
return self.left + self.width
def set_right(self, right):
self.width = right-self.left
right = property(get_right, set_right)
def get_bottom(self):
return self.top + self.height
def set_bottom(self, bottom):
self.height = bottom - self.top
bottom = property(get_bottom, set_bottom)
def __getitem__(self, i):
if i == 0:
return int(self.left)
if i == 1:
return int(self.top)
if i == 2:
return int(self.width)
if i == 3:
return int(self.height)
def __len__(self):
return 4
class Ball(pygame.sprite.Sprite):
"""Renders the ball and does the corresponding logic"""
def __init__(self, pong):
pygame.sprite.Sprite.__init__(self)
self.pong = pong
self.image = pygame.Surface((20, 20), pygame.HWSURFACE)
self.image.fill(BLACK)
pygame.draw.circle(self.image, (255, 255, 255), (10, 10), 10)
self.image.set_colorkey(BLACK)
self.rect = Rect(self.pong.width/2.0, self.pong.height/2.0, 20, 20)
self.vx = 0.6
self.vy = 0.8
def update(self, t):
newrect = Rect(self.rect.left + self.vx * t, self.rect.top + self.vy*t,
self.rect.width, self.rect.height)
# hit userpanel?
if self.rect.left >= self.pong.userpanel.rect.right\
and newrect.left <= self.pong.userpanel.rect.right\
and self.rect.top + ((self.rect.left\
- self.pong.userpanel.rect.right)\
/ (self.rect.left - newrect.left))*t*self.vy\
< self.pong.userpanel.rect.bottom\
and self.rect.top + ((self.rect.left\
- self.pong.userpanel.rect.right)\
/ (self.rect.left - newrect.left))*t*self.vy\
> self.pong.userpanel.rect.top:
self.rect.left = 2 * self.pong.userpanel.rect.right - newrect.left
self.vx *= -1
# hit ai panel
elif self.rect.right <= self.pong.aipanel.rect.left\
and newrect.right >= self.pong.aipanel.rect.left\
and self.rect.top + ((self.rect.right\
- self.pong.aipanel.rect.right)\
/ (self.rect.right - newrect.right)) * t * self.vy\
< self.pong.aipanel.rect.bottom\
and self.rect.top + ((self.rect.right\
- self.pong.aipanel.rect.right)\
/ (self.rect.right - newrect.right)) * t * self.vy\
> self.pong.aipanel.rect.top:
self.rect.right = 2 * self.pong.aipanel.rect.left - newrect.right
self.vx *= -1
# hit left?
elif newrect.left <= 0:
self.pong.score.player2 += 1
self.rect.left = -newrect.left
self.vx *= -1
# hit right?
elif newrect.right >= self.pong.width:
self.pong.score.player1 += 1
self.vx *= -1
else:
self.rect.left = newrect.left
# hit top?
if newrect.top <= 0:
self.vy *= -1
self.rect.top = -newrect.top
# hit bottom?
elif newrect.bottom >= self.pong.height:
self.vy *= -1
self.rect.bottom = 2*self.pong.height-(newrect.bottom)
# hit nothing...
else:
self.rect.top = newrect.top
class Panel(pygame.sprite.Sprite):
"""Base Panel"""
def __init__(self, pong, x):
pygame.sprite.Sprite.__init__(self)
self.pong = pong
self.image = pygame.Surface((10, 100), pygame.HWSURFACE)
self.image.fill(WHITE)
self.rect = pygame.Rect(x, 10, 10, 100)
def move(self, y):
self.rect.top = y - self.rect.height/2
class UserPanel(Panel):
"""User Controlled Panel"""
def __init__(self, pong, x):
Panel.__init__(self, pong, x)
def update(self, t):
self.move(pygame.mouse.get_pos()[1])
class AIPanel(Panel):
"""Computer Controlled Panel"""
def __init__(self, pong, x):
Panel.__init__(self, pong, x)
self.speed = 0.8
self.move(pong.height/2)
def update(self, t):
diff = self.pong.ball.rect.top - self.rect.centery
if diff > self.speed*t:
diff = self.speed*t
elif diff*-1 > self.speed*t:
diff = self.speed*t*-1
if diff > 0 and diff < 1:
diff = 1
elif diff < 0 and diff > -1:
diff = -1
self.move(math.ceil(self.rect.centery+diff))
class Score(pygame.sprite.Sprite):
"""Displays the current score"""
def __init__(self, pong):
pygame.sprite.Sprite.__init__(self)
self.pong = pong
self.image = pygame.Surface((200, 80), pygame.HWSURFACE)
self.rect = pygame.Rect(pong.width/2-100, 10, 200, 80)
self.font = pygame.font.SysFont("Monospaceh", 32)
self.font.set_bold(True)
self.font.set_italic(False)
self._player1 = 0
self._player2 = 0
colonpos = 100-self.font.size(":")[0]/2
self.image.blit(self.font.render(":", 1, (255, 255, 255)),
(colonpos, 0))
self.render_player1()
self.render_player2()
def get_player1(self):
return self._player1
def set_player1(self, score):
self._player1 = score
self.render_player1()
player1 = property(get_player1, set_player1)
def render_player1(self):
self.image.fill(BLACK, (0, 0, 90, 80))
pos = 90-self.font.size(str(self._player1))[0]
self.image.blit(self.font.render(str(self._player1), 2, WHITE),
(pos, 0))
def get_player2(self):
return self._player2
def set_player2(self, score):
self._player2 = score
self.render_player2()
player2 = property(get_player2, set_player2)
def render_player2(self):
self.image.fill(BLACK, (110, 0, 100, 80))
self.image.blit(self.font.render(str(self._player2), 2, WHITE),
(110, 0))
class Pong(object):
"""The pong game class"""
def __init__(self, width=800, height=600, fullscreen=False):
pygame.display.init()
pygame.font.init()
self.width = width
self.height = height
modes = pygame.HWSURFACE | pygame.DOUBLEBUF
if fullscreen:
modes |= pygame.FULLSCREEN
self.screen = pygame.display.set_mode((width, height), modes)
pygame.display.set_caption('PyPong')
self.screen.fill(BLACK)
self.clock = pygame.time.Clock()
self.ball = Ball(self)
self.userpanel = UserPanel(self, 10)
self.aipanel = AIPanel(self, width-20)
self.score = Score(self)
self.sprites = pygame.sprite.OrderedUpdates((self.score,
self.userpanel, self.aipanel,self.ball))
self.main()
def main(self):
i = 0
print ""
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
elif event.type == pygame.KEYUP:
if event.key == pygame.K_ESCAPE:
return
self.tick(self.clock.tick(250))
# for some reason sdl does busy waiting using clock.tick()
# this takes away the load from the cpu
time.sleep(0.000005)
i += 1
if i % 100 == 0:
print "\033[1F%s FPS" % str(
round(self.clock.get_fps())).rjust(8," ")
def tick(self, t):
if t == 0:
return
self.sprites.update(t)
self.sprites.clear(self.screen,
lambda surf,rect: surf.fill((0,0,0), rect))
pygame.display.update(self.sprites.draw(self.screen))
if __name__ == "__main__":
# psyco seems to be useless here O_o
#try:
# import psyco
# print "Using psyco!"
#except ImportError:
# print "Psyco not avaible"
APP = sys.argv.pop(0)
if(len(sys.argv) == 0):
Pong()
elif(len(sys.argv) == 2):
Pong(int(sys.argv[0]), int(sys.argv[1]))
elif(len(sys.argv) == 3):
Pong(int(sys.argv[0]), int(sys.argv[1]), sys.argv[2]=="fullscreen")
else:
print "Usage: %s [width height [fullscreen]]" % APP