I am trying to create a numpad.
The way I try to making the numpad is like:
class One:
def __init__(self,c,msg):
self.screen = c.calculator
self.screen_rect = self.screen.get_rect()
self.settings = c.settings
self.width,self.height = 60,60
self.button_color = (230,230,230)
self.text_color = (100,100,100)
self.rect = pygame.Rect(30,600,self.width,self.height)
self.font = pygame.font.SysFont('Comic Sans MS',20,bold=pygame.font.Font.bold)
self._prep_msg(msg)
def _prep_msg(self,msg):
self.msg_image = self.font.render(msg,True,self.text_color,self.button_color)
self.msg_image_rect = self.msg_image.get_rect()
self.msg_image_rect.center = self.rect.center
def draw_button(self):
self.screen.fill(self.button_color,self.rect)
self.screen.blit(self.msg)
This way is requires a lot of code, making one class each for like 9 numbers.
I hoping if there was more optimal way of making this numpad.
I think of making sprites but I don't know how I will change the text:
self.One = One(self,"1")
If there is something you can't understand please ask.
Thank you for help!
Read about Classes. You can instantiate a class multiple times. e.g.:
Create a Button. The position of the button is an argument to the constructor:
class Button:
def __init__(self, c, msg, x, y): # <--- x, y
self.screen = c.calculator
self.screen_rect = self.screen.get_rect()
self.settings = c.settings
self.width,self.height = 60,60
self.button_color = (230,230,230)
self.text_color = (100,100,100)
self.rect = pygame.Rect(x, y, self.width, self.height) # <--- x, y
self.font = pygame.font.SysFont('Comic Sans MS',20,bold=pygame.font.Font.bold)
self._prep_msg(msg)
def _prep_msg(self,msg):
self.msg_image = self.font.render(msg,True,self.text_color,self.button_color)
self.msg_image_rect = self.msg_image.get_rect()
self.msg_image_rect.center = self.rect.center
def draw_button(self):
self.screen.fill(self.button_color,self.rect)
self.screen.blit(self.msg)
Create multiple Instance Objects of the class Button:
self.button_one = Button(self, "1", 30, 600)
self.button_two = Button(self, "2", 100, 600)
Related
What am I doing wrong here?
I want to update the text of the label to accommodate a player score.
I've looked at other examples and added the update method but the text still stays the same.
class Label():
def __init__(self, txt, location, size=(160,30), bg=WHITE, fg=BLACK, font_name="Segoe Print", font_size=12):
self.bg = bg
self.fg = fg
self.size = size
self.font = pygame.font.Font(font_name, font_size)
self.txt = txt
self.txt_surf = self.font.render(self.txt, 1, self.fg)
self.txt_rect = self.txt_surf.get_rect(center=[s//2 for s in self.size])
self.surface = pygame.surface.Surface(size)
self.rect = self.surface.get_rect(topleft=location)
def draw(self):
self.surface.fill(self.bg)
self.surface.blit(self.txt_surf, self.txt_rect)
screen.blit(self.surface, self.rect)
def update(self):
self.txt_surf = self.font.render(self.txt, 1, self.fg)
self.surface.blit(self.txt_surf, self.txt_rect)
You can simply assign the current score (convert it into a string first) to the .txt attribute of your label object and then call its update method.
# In the main while loop.
score += 1
label.txt = str(score)
label.update()
I would also just blit the surface in the draw method and update it in the update method.
def draw(self, screen):
screen.blit(self.surface, self.rect)
def update(self):
self.surface.fill(self.bg)
self.txt_surf = self.font.render(self.txt, True, self.fg)
self.surface.blit(self.txt_surf, self.txt_rect)
I am creating a simulator in pygame for school. I have created 3 buttons, which change colur when you hover. However, I want one of the buttons to have smaller text in. Currently, to set the text I have it within a class, but not as a method. I have made the button smaller when calling it as an instance, but I am not sure how to make the text smaller for this button, without changing the text in the others.
this is my code for my button class
class button():
def __init__(self, color, x , y , width , height , text=''):
self.color = color
self.x = x
self.y = y
self.width = width
self.height = height
self.text = text
def draw(self,win,outline= None):
if outline:
pygame.draw.rect(win, outline, (self.x-2 , self.y-2, self.width+4, self.height+4),0)
pygame.draw.rect(win, self.color, (self.x , self.y , self.width, self.height),0)
if self.text != '':
font = pygame.font.SysFont( "Times New Roman,Arial",40, bold = True)
text = font.render(self.text, 1 , (0,0,0))
win.blit(text, (self.x +(self.width/2 - text.get_width()/2), self.y + (self.height/2 - text.get_height()/2)))
def isOver(self,pos):
if pos[0] > self.x and pos [0] < self.x + self.width:
if pos [1] > self.y and pos[1] < self.y + self.height:
return True
return False
def redrawWindow():
userButton.draw(win,(0,0,0))
passButton.draw(win,(0,0,0))
loginButton.draw(win,(0,0,0))
this is the code for creating the instances:
userButton = button((TURQUOISE), 300,225,400,100, 'Username' )
passButton = button((TURQUOISE), 300,350,400,100, 'Password' )
loginButton = button((TURQUOISE), 465,470,100,25, 'Login' )
Just add an additional argument textSize to the contrcutor of the button:
class button():
def __init__(self, color, x , y , width , height , text='', textSize = 40):
self.color = color
self.x = x
self.y = y
self.width = width
self.height = height
self.text = text
self.textSize = textSize
def draw(self,win,outline= None):
# [...]
if self.text != '':
font = pygame.font.SysFont( "Times New Roman,Arial", self.textSize, bold = True)
Pass the size of the text to the constructor. For isntance
userButton = button((TURQUOISE), 300,225,400,100, 'Username', 40)
passButton = button((TURQUOISE), 300,350,400,100, 'Password', 40)
loginButton = button((TURQUOISE), 465,470,100,25, 'Login', 30)
However creating a font object is a very expensive operation. You should avoid creating the font once per frame or even once per button drawing. See How to render/blit text in pygame for good performance.
I recommend to create the different fonts once at the begin of the application:
font30 = pygame.font.SysFont("Times New Roman,Arial", 30, bold = True)
font40 = pygame.font.SysFont("Times New Roman,Arial", 40, bold = True)
Add font attribute to the class instead of the text size attribute:
class button():
def __init__(self, color, x, y, width, height, font, text=''):
self.color = color
self.x = x
self.y = y
self.width = width
self.height = height
self.font = font
self.text = text
def draw(self,win,outline= None):
# [...]
if self.text != '':
text = self.font.render(self.text, 1 , (0,0,0))
Pass the font object to the constructor of button. For instance:
userButton = button((TURQUOISE), 300,225,400,100, font40, 'Username')
passButton = button((TURQUOISE), 300,350,400,100, font40, 'Password')
loginButton = button((TURQUOISE), 465,470,100,25, font30, 'Login')
I am trying to blit text onto a screen, but only using classes. When I create an instance from a class, is there any way to reference that same instance within the class? For example, in my code:
class _text_():
def __init__(self, font, size, text, antialias, colour, background):
self.font = font
self.size = size
self.text = text
self.antialias = antialias
self.colour = colour
self.background = background
def _textsettings_(self):
texts = pygame.font.SysFont(self.font, self.size)
return texts.render(self.text, self.antialias, self.colour, self.background)
def _textblit_(self):
return win.blit[text1, (400, 240)]
text1 = _text_('calibri', 20, "press any button to start", True, black, None)
in the textblit function, I am trying to use variable 'text1' so that I can blit it to screen, but obviously this isn't working and I am stumped as to how to do it.
Any suggestions appreciated!
The text surface becomes an instance attribute of the class (self.text):
class _text_():
def __init__(self, font, size, text, antialias, colour, background):
self.font = font
self.size = size
self.text = text
self.antialias = antialias
self.colour = colour
self.background = background
texts = pygame.font.SysFont(self.font, self.size)
self.text = texts.render(self.text, self.antialias, self.colour, self.background)
def _textblit_(self):
win.blit(self.text, (400, 240))
Call _textblit_ in the main application loop:
text1 = _text_('calibri', 20, "press any button to start", True, black, None)
while True:
# [...]
text1._textblit_()
# [...]
This is the class :
name file = text.py
import pygame
class _text_():
def __init__(self,text):
pygame.init()
self.text = text
self.antialias = True
self.colour = (255,255,255)
self.background = None
self.font = pygame.font.SysFont("arialblack",40)
self.img = self.font.render(self.text, self.antialias, self.colour,self.background)
def _textblit_(self,surface):
surface.blit(self.img,(400,240))
This is the test
import pygame
from text import _text_
SCREEN_HEIGHT = 800
SCREEN_WIDTH = 1200
screen = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))
text1 = _text_(": )")
run = True
while run:
screen.fill((52,78,91))
text1._textblit_(screen)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.display.update()
pygame.quit()
I am trying to make a python library:
There is a class (game) in it is a function that defines a variable (display)
Then there is another class (char) in main, I want to access display in char
How do I do it?
In the past I have tried: self.display, global display, and game.display
class game():
def __init__(self, disp, width, height):
self.display = disp # VARIABLE I WANT TO ACCESS
self.height = height
self.width = width
class sprite():
def __init__(self, size, position, image):
self.image = image
self.size = size
self.rect = self.image.get_rect()
self.rect.x = position[0]
self.rect.y = position[1]
self.x = position[0]
self.y = position[1]
self.collisionDirection = 5
self.hasCollided = False
self.mask = pygame.mask.from_surface(self.image)
self.velocity = 0
def render(self):
self.rect.x = self.x
self.rect.y = self.y
self.mask = pygame.mask.from_surface(self.image)
display.blit(self.image, (self.x, self.y)) # WHERE I WANT TO ACCESS IT
I keep getting AttributeError what can I do?
You can pass the Game instance to another class. For example
# instantiate the game
g = game()
# create an instance of char
c = char(game)
assuming the __init__ of char() looks something like this:
class char():
def __init__(self, game):
# save a reference to the game object as an attribute
self.game = game
# now you can access the game's attributes
print(self.game.display)
Allow that the below example is contrived, and not likely the way you would design pen/paper, but it shows that there are a couple different ways that you can accomplish what you ask.
class Pen:
def __init__(self, thickness, color):
self.thickness = thickness
self.color = color
class Paper:
def __init__(self, pen: Pen):
self.pen = pen
def draw(self):
pen_color = self.pen.color
return pen_color
def draw2(self, pen: Pen):
pen_color = pen.color
return pen_color
red_pin = Pen(2, 'Red')
blue_pin = Pen(1, 'Blue')
paper = Paper(red_pin)
print(paper.draw()) # prints Red
print(paper.draw2(blue_pin)) # prints Blue
I have been following a guide to make my game. However, when I try to run the program I get a syntax Error with the Class Circle and not sure why? I can't figure out the reason and I'm sure there are more issue afterward the Class Circle but can't fix it.
import pygame
from pygame.locals import *
from uagame import Window
import time
import random
def main():
window = Window('Pong', 500, 400)
window.set_auto_update(False)
game = Game(window)
game.play()
window.close()
class Rect:
def __init__(self, center, radius, color, window):
self.center = center
self.radius = radius
self.color = color
self.window = window
def draw(self):
pygame.draw.rect(self.window.get_surface(), self.color, Rect((100, 200), (20, 30))
class Circle: # Syntax Error: class Circle:: <string>, line 28, pos 5
def __init__(self, center, radius, color, window):
self.center = center
self.radius = radius
self.color = color
self.window = window
def draw(self):
pygame.draw.circle(self.window.get_surface(), self.color, self.center,self.radius)
def get_color(self):
return self.color
def move(self):
window_size = (self.window.get_width() , self.window.get_height())
for index in range(0,2):
self.center[index] = (self.center[index] + 1) % window_size[index]
def enlarge(self,increment):
self.radius = self.radius + increment
class Game:
def __init__(self, window):
self.window = window
self.bg_color = pygame.Color('black')
self.fg_color = 'green'
self.rect_color = 'green'
self.pause_time = 0.02
self.close_clicked = False
self.continue_game = True
self.circle = Ball([200,200], 20, pygame.Color(self.fg_color),window)
self.rect = Rect([100,200], 50 , pygame.Color(self.fg_color),window)
self.radius_increment = 5
def play(self):
while not self.close_clicked:
self.handle_event()
self.draw()
if self.continue_game:
self.update()
self.decide_continue()
time.sleep(self.pause_time)
def handle_event(self):
event = pygame.event.poll()
if event.type == QUIT:
self.close_clicked = True
elif event.type == MOUSEBUTTONUP and self.continue_game:
self.handle_mouse_up()
def handle_mouse_up(self):
self.circle.enlarge(self.radius_increment)
def draw(self):
self.window.clear()
self.circle.draw()
self.rect.draw()
if not self.continue_game:
self.window.set_bg_color(self.fg_color)
self.window.clear()
self.window.update()
def update(self):
self.circle.move()
def decide_continue(self):
pass
main()
Your error actually lies in the line above. See that your code is missing a parenthesis to close the rect() function. Always remember to count the parenthesis on long functions like this.
def draw(self):
pygame.draw.rect(self.window.get_surface(), self.color, Rect((100, 200), (20, 30))) #<-