Spiel "Pong"

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
JonBach18
User
Beiträge: 46
Registriert: Dienstag 22. Dezember 2020, 13:32

Hallo Leute,

ich bin fast fertig mit meinem Spiel und wollte eure Meinung dazu hören, was Ihr dazu sagt.
Ich habe auch noch eine Fragen wie ist es möglich das man nur bis 5 Spielt und es dann zu Ende geht und man von vorne anfangen kann ?
Mein Code

Code: Alles auswählen

# Importieren einer Bibiothek
import pygame
from pygame.locals import *

#Pygame initialisieren
pygame.init()
# Bilschirm Größe
screen_breite = 600
screen_höhe = 500


Clock = pygame.time.Clock()
# Bilschirm ertsllen mit Überschrift
screen = pygame.display.set_mode((screen_breite, screen_höhe))
pygame.display.set_caption('Pong von Ramon')


#define font
font = pygame.font.SysFont('Constantia', 30)



#define game variables
margin = 50
cpu_score = 0
player_score = 0
fps = 60
live_ball = False
winner = 0
speed_increase = 0


#define colours
bg = pygame.Color("#2F373F")
white = (255, 255, 255)
blue = (58,144,255)


def draw_board():
	screen.fill(bg)
	pygame.draw.line(screen,white,(0, margin),(screen_breite, margin), 2)
	pygame.draw.line(screen,white,(300,50),(300,500),2)


# Man kann nicht direkt einen Text schreiben, mann muss es den text in ein Bild konvertieren und diesen mit screen.blit
# auf das "Screen" tun / x und y steht für wo der "Text" am Ende wo es sein soll // font muss noch bestimmt werden //
# text ist der text den man sehen möchte
def draw_text(text, font, text_col, x, y):
	img = font.render(text, True, text_col)
	screen.blit(img, (x, y))


class paddle():
	def __init__(self, x, y):
		self.x = x
		self.y = y
		self.rect = Rect(x, y, 20, 100)
		self.speed = 5
		self.ai_speed = 5

	def move(self):
		key = pygame.key.get_pressed()
		if key[pygame.K_UP] and self.rect.top > margin:
			self.rect.move_ip(0, -1 * self.speed)
		if key[pygame.K_DOWN] and self.rect.bottom < screen_höhe:
			self.rect.move_ip(0, self.speed)

	def draw(self):
		pygame.draw.rect(screen, white, self.rect)


	def ai(self):
		#ai to move the paddle automatically
		#move down
		if self.rect.centery < pong.rect.top and self.rect.bottom < screen_höhe:
			self.rect.move_ip(0, self.ai_speed)
		#move up
		if self.rect.centery > pong.rect.bottom and self.rect.top > margin:
			self.rect.move_ip(0, -1 * self.ai_speed)



class ball():
	def __init__(self, x, y):
		self.reset(x, y)


	def move(self):

		#check collision with top margin
		if self.rect.top < margin:
			self.speed_y *= -1
		#check collision with bottom of the screen
		if self.rect.bottom > screen_höhe:
			self.speed_y *= -1
		if self.rect.colliderect(player_paddle) or self.rect.colliderect(cpu_paddle):
			self.speed_x *= -1

		#check for out of bounds
		if self.rect.left < 0:
			self.winner = 1
		if self.rect.left > screen_breite:
			self.winner = -1

		#update ball position
		self.rect.x += self.speed_x
		self.rect.y += self.speed_y

		return self.winner


	def draw(self):
		pygame.draw.circle(screen, white, (self.rect.x + self.ball_rad, self.rect.y + self.ball_rad), self.ball_rad)


	def reset(self, x, y):
		self.x = x
		self.y = y
		self.ball_rad = 8
		self.rect = Rect(x, y, self.ball_rad * 2, self.ball_rad * 2)
		self.speed_x = -4
		self.speed_y = 4
		self.winner = 0# 1 is the player and -1 is the CPU

	def resset_ball(self):
		self.active = False
		self.speed_x *= random.choice((-1,1))
		self.speed_y *= random.choice((-1,1))
		self.score_time = pygame.time.get_ticks()
		self.rect.center = (screen_breite / 2, screen_höhe / 2)


#create paddles
player_paddle = paddle(screen_breite - 40, screen_höhe // 2)
cpu_paddle = paddle(20, screen_höhe // 2)

#create pong ball
pong = ball(screen_breite - 60, screen_höhe // 2 + 50)


#create game loop
run = True
while run:

	Clock.tick(fps)

	draw_board()
	draw_text('AI: ' + str(cpu_score), font, white, 20, 15)
	draw_text('P1: ' + str(player_score), font, white, screen_breite - 100, 15)
	draw_text('BALL SPEED: ' + str(abs(pong.speed_x)), font, white, screen_breite // 2 - 100 , 15)


	#draw paddles
	player_paddle.draw()
	cpu_paddle.draw()

	if live_ball == True:
		speed_increase += 1
		winner = pong.move()
		if winner == 0:
			#draw ball
			pong.draw()
			#move paddles
			player_paddle.move()
			cpu_paddle.ai()
		else:
			live_ball = False
			if winner == 1:
				player_score += 1
			elif winner == -1:
				cpu_score += 1


	#print player instructions
	if live_ball == False:
		if winner == 0:
			draw_text('Zum Starten klicken', font, blue, 200, screen_höhe // 2 -100)
		if winner == 1:
			draw_text('YOU SCORED!', font, white, 220, screen_höhe // 2 -100)
			draw_text('CLICK ANYWHERE TO START', font, white, 100, screen_höhe // 2 -50)
		if winner == -1:
			draw_text('CPU SCORED!', font, white, 220, screen_höhe // 2 -100)
			draw_text('CLICK ANYWHERE TO START', font, white, 100, screen_höhe // 2 -50)



	for event in pygame.event.get():
		if event.type == pygame.QUIT:
			run = False
		if event.type == pygame.MOUSEBUTTONDOWN and live_ball == False:
			live_ball = True
			pong.reset(screen_breite - 60, screen_höhe // 2 + 50)



	if speed_increase > 500:
		speed_increase = 0
		if pong.speed_x < 0:
			pong.speed_x -= 1
		if pong.speed_x > 0:
			pong.speed_x += 1
		if pong.speed_y < 0:
			pong.speed_y -= 1
		if pong.speed_y > 0:
			pong.speed_y += 1


	pygame.display.update()

pygame.quit()
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

Eingerückt wird immer mit 4 Leerzeichen pro Ebene, keine Tabs.
Konstanten schreibt man komplett GROSS, Variablennamen komplett klein und Klassen mit großem Anfangsbuchstaben.
Auf oberster Ebene darf kein ausführbarer Code stehen, sondern das sollte alles eine einer Funktion, die üblicherweise main genannt wird, stehen.
Man vergleicht nicht explizit mit True oder False, und wenn der zweite if-Block genau die gegenteilige Bedingung hat, dann benutzt man else:
In ball.move kommen player_paddle und cpu_paddle aus dem Nichts, das sollten Argumente sein.
Nur in ball.move wird winner verwendet, das muß also kein Attribut sein. Genauso wird active gar nicht verwendet.
JonBach18
User
Beiträge: 46
Registriert: Dienstag 22. Dezember 2020, 13:32

Danke für deine Antwort.
Was meinst du mit "es darf nicht in der obersten Ebene kein ausführbarer Code stehen, sondern das sollte alles eine einer Funktion, die üblicherweise main genannt wird, stehen."
Würde mich freuen wenn du mir es erklären könntest. Freue mich immer wieder wenn ich was neues lerne :)
Benutzeravatar
sparrow
User
Beiträge: 4538
Registriert: Freitag 17. April 2009, 10:28

@JonBach18: Auf der Modulebene (also der obersten Ebene, quasi die nicht eingerückten Zeilen) dürfen nur die Importe und die Definitionen von KONSTANTEN, Klassen und funktionen stehen (achte auf die Namensgebung). Das Grundgerüst eines Programms sieht wie folgt aus:

Code: Alles auswählen

def main():
    # your program here

if __name__ == "__main__":
    main()
Das Programm kommt dann in die Funktion "main".
Machten tut man das, weil Code auf Modulebene ausgeführt wird, sobald das Modul importiert wird. Das ist unerwartetes Verhalten und man sollte sich das erst gar nicht angewöhnen. Du kannst auch nicht davon ausgehen, dass dein Programm nie als Modul importiert wird, weil verschiedene Tools rund um die Entwicklung das tun.

Die letzten beiden Zeilen sorgen dafür, dass die Funktion "main" nur ausgeführt wird, wenn die Datei, in der sie steht, die Datei ist, die gestartet wurde. Wird das Modul importiert, wird nichts ausgeführt.
Antworten