Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Pygame Help
#1
Hello! I have been running into a issue with drawing rectangles, blitting text, querying a DB etc etc inside the game loop. The rectangles or text appear on screen for on fps (I think) and then disappears. The sql call,. calls every fps etc etc. I have tried to figure out how to do this outside the loop without success. I'm sure I am just missing something stupid. This is an example of a Yahtzee game I am "trying" to quickly throw together to learn. Inside the SetTableDice function it renders the "dice" but only for a quick second. Any insights?

import sys
import os
import time
import random
from collections import Counter
import pygame

pygame.init()

screen_width = 800
screen_height = 600
first_table_dice_x_position = 150;
screen = pygame.display.set_mode((screen_width, screen_height))
smallfont = pygame.font.SysFont('Corbel',20)
clock = pygame.time.Clock()
game_over = False

class Dice():
	DiceOnTable = {'d1': 1, 'd2': 2, 'd3': 3, 'd4': 4, 'd5': 6}
	turn = False

	def __inti__(self):
		pass

	def RollDice(self):
		# self.DiceOnTable.clear()

		for k in self.DiceOnTable:
			dice = random.randint(1, 6)
			self.DiceOnTable[k] = dice
			self.turn = True

		

		# sort might be needed in the future
		# self.DiceOnTable = {k: v for k, v in sorted(self.DiceOnTable.items(), key=lambda item: item[1])}

		print(self.DiceOnTable)
		# while self.turn:
		# d1 = smallfont.render(str(self.DiceOnTable['d1']), True , (0,0,0))
		# wtf = smallfont.render('WTF??', True , (0,0,0))
		# screen.blit(wtf, (100,100))
		# screen.blit(d1, (first_table_dice_x_position,250))


	def SetTableDice(self):
		d1 = self.DiceOnTable['d1'];

		pygame.draw.rect(screen,(255,255,255),[first_table_dice_x_position,250,35,40])

		d1 = smallfont.render(str(d1), True , (0,0,0))
		screen.blit(d1, (first_table_dice_x_position,250))

		# while self.turn:
		# 	time.sleep()

		# pygame.display.update()

		# time.sleep(2)

		# GameLoop()

	def CheckDice(self):
		for v in range(6):
			self.CheckForTop(v)
		
		self.CheckForChance()
		self.CheckForMultiples()
		self.CheckForLargeStraight()
		self.CheckForSmallStraight()

	def CheckForTop(self, num):
		NumOf = []
		for v in self.DiceOnTable:
			if str(self.DiceOnTable[v]) == str(num):
				NumOf.append(1)
		HowMany = str(len(NumOf))
		print('You have ' + HowMany + ' ' + str(num))

	def CheckForMultiples(self):
		counts = Counter(self.DiceOnTable.values())
		TwoOfAKind = False
		ThreeOfAKind = False

		for v in counts:
			if counts[v] == 5:
				print("You have a yahtzee with " + str(v))
			if counts[v] == 4:
				print("You have a four of a kind with " + str(v))
			if counts[v] == 2:
				TwoOfAKind = True
				print("You have a two of a kind with " + str(v))
			if counts[v] == 3:
				ThreeOfAKind = True
				print("You have a three of a kind with " + str(v))

		if TwoOfAKind and ThreeOfAKind:
				print("You have a full house")

	def CheckForLargeStraight(self):
		#the below could be done better - needs refactoring
		# self.DiceOnTable = {k: v for k, v in sorted(self.DiceOnTable.items(), key=lambda item: item[1])}

		print(self.DiceOnTable)

		if ((1 in self.DiceOnTable.values() and
				2 in self.DiceOnTable.values() and
				3 in self.DiceOnTable.values() and
				4 in self.DiceOnTable.values() and
				5 in self.DiceOnTable.values()) or
				(2 in self.DiceOnTable.values() and
				3 in self.DiceOnTable.values() and
				4 in self.DiceOnTable.values() and
				5 in self.DiceOnTable.values() and
				6 in self.DiceOnTable.values())):
			print('You have a large straight!')

	def CheckForSmallStraight(self):
		#the below could be done better - needs refactoring
		# self.DiceOnTable = {k: v for k, v in sorted(self.DiceOnTable.items(), key=lambda item: item[1])}

		if ((1 in self.DiceOnTable.values() and
				2 in self.DiceOnTable.values() and
				3 in self.DiceOnTable.values() and
				4 in self.DiceOnTable.values()) or
				(2 in self.DiceOnTable.values() and
				3 in self.DiceOnTable.values() and
				4 in self.DiceOnTable.values() and
				5 in self.DiceOnTable.values()) or
				(3 in self.DiceOnTable.values() and
				4 in self.DiceOnTable.values() and
				5 in self.DiceOnTable.values() and
				6 in self.DiceOnTable.values())):
			print('You have a small straight!')

	def CheckForChance(self):
		total = 0

		for v in self.DiceOnTable:
			total += self.DiceOnTable[v]

		print("Chance = " + str(total))

	def CreateTableDice(self):
		# for k in self.DiceOnTable:
		pass

def GameLoop():
	while not game_over:
		screen.fill((0,102,0))
		pygame.draw.rect(screen,(255,255,255),[530,20,250,550])
		text = smallfont.render('Roll Dice' , True , (255,255,255))
		pygame.draw.rect(screen,(0,0,0),[200,450,140,40])
		screen.blit(text , (240,460))
		# pygame.draw.rect(screen,(255,255,255),[first_table_dice_x_position,250,35,40])
		# pygame.draw.rect(screen,(255,255,255),[first_table_dice_x_position+40,250,35,40])
		# pygame.draw.rect(screen,(255,255,255),[first_table_dice_x_position+80,250,35,40])
		# pygame.draw.rect(screen,(255,255,255),[first_table_dice_x_position+120,250,35,40])
		# pygame.draw.rect(screen,(255,255,255),[first_table_dice_x_position+160,250,35,40])
		# pygame.draw.rect(screen,(255,255,255),[first_table_dice_x_position+200,250,35,40])
		mouse = pygame.mouse.get_pos()

		for event in pygame.event.get():
			# print(event)
			if event.type == pygame.QUIT:
				sys.exit()

			if event.type == pygame.MOUSEBUTTONDOWN:
	              
				if 200 <= mouse[0] <= 200+140 and 450 <= mouse[1] <= 450+40:
					dice = Dice()
					dice.RollDice()
					dice.CheckDice()
					dice.SetTableDice()

			if event.type == pygame.KEYDOWN:

				if event.key == pygame.K_ESCAPE:
					sys.exit()



		clock.tick(30)

		pygame.display.update()


GameLoop()

pygame.quit()
quit()
Reply
#2
So a little more insight. The rect is doing exactly what I told it to do. On click of the button it shows up,. but immediately goes away. How would I "pause" the game waiting on user input? Like the user clicking the dice to select them?
Reply
#3
On line 171 you reset dice to a new iteration of Dice each time the "roll dice' button is pressed. It might be best to do this only once, perhaps at the beginning of Gameloop like this:

def GameLoop():
    dice = Dice()
    while not game_over:
The problem that you're having is because dice.SetTableDice () only updates the dice when "roll dice" is clicked. I recommend that you move it down with pygame.display.update () like this:

        clock.tick(30)
        dice.SetTableDice () 
        pygame.display.update()
Reply
#4
Quote:The problem that you're having is because dice.SetTableDice () only updates the dice when "roll dice" is clicked. I recommend that you move it down with pygame.display.update () like this:

Ok at first I didn't understand this and dismissed it. But then I tried it,. and I'm having a hard time wrapping my head around,. but it does put me on a new track. So thank you for that! It seems I have a lot to learn about this game loop.
Reply
#5
So all I have to do now is update the variable's name. Furthermore, the variables must be distinct from the class name.
If that is the only method to fix it, it will not work. I've tried changing several names, but each time I get the same problem. Maybe I'm mistaken.
But, Gribouillis, thank you very much for your time. Refer to super mario bros.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020