Pygame - Pong!
Verfasst: Mittwoch 28. Februar 2007, 20:29
Ich habe mich mal an pygame versucht und ein einfaches Pong gebaut. Scheint sogar relativ schnell zu laufen.
Da ich noch nicht viel Erfahrung mit Python habe würde ich mich über Feedback natürlich sehr freuen.
Aber nun zum Code:
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