Related
I'm not managing to get this math correct, and it's a little bit difficult to explain in words. I have managed to create a isometric grid, which you can select the tiles with the mouse perfectly, and I have managed to implement a camera movement using wasd keys and still get the tiles correctly selected, but there is a slightly bug which I can not figure out where is coming from.
This is what happens, but only sometimes, depend where the camera offset is:
when this happens, it is only on the x axis, and not in every tile.
I'm almost giving up on this cause I can't find the bug, thought of posting here to see if anyone had similar problem.
import time
import pygame
import sys
import math
from os import path
from settings import *
from sprites import *
# ------------------------- SETTINGS ---------------------------- #
# COLORS (r, g, b)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
DARKGREY = (40, 40, 40)
LIGHTGREY = (100, 100, 100)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)
# game settings
WIDTH = 1024
HEIGHT = 768
FPS = 60
title = "Isometric-Based game"
BGCOLOUR = DARKGREY
TILE_X = 80
TILE_Y = 40
WORLD_X, WORLD_Y = 14, 10
ORIGIN_X, ORIGIN_Y = 5, 1
# Debug
pygame.init()
font = pygame.font.Font(None, 25)
CAMERA_SPEED = 300
def get_info(info_list):
display_surface = pygame.display.get_surface()
for i, key in enumerate(info_list):
text = font.render(str(key) + " : " + str(info_list[key]), True, (255, 255, 255), (0, 0, 0))
text_rect = text.get_rect()
text_rect.y = 20 * i
display_surface.blit(text, text_rect)
# ------------------------- SPRITES ---------------------------- #
class Camera:
def __init__(self, game, x, y):
self.game = game
self.x, self.y = self.game.to_screen(x, y)
self.vx, self.vy = 0, 0
def update(self):
self.get_keys()
self.x += self.vx * self.game.dt
self.y += self.vy * self.game.dt
def get_keys(self):
self.vx, self.vy = 0, 0
keys = pygame.key.get_pressed()
if keys[pygame.K_w]:
self.vy = -CAMERA_SPEED
if keys[pygame.K_s]:
self.vy = CAMERA_SPEED
if keys[pygame.K_a]:
self.vx = -CAMERA_SPEED
if keys[pygame.K_d]:
self.vx = CAMERA_SPEED
if self.vx != 0 and self.vy != 0:
self.vx *= 1.0
self.vy *= 0.50
class MouseSelection:
def __init__(self, game, image):
self.game = game
self.image = image
def update(self):
# get mouse x and y
self.mouse_x, self.mouse_y = pygame.mouse.get_pos()
# get the mouse offset position inside the tile
self.offset_x, self.offset_y = self.mouse_x % TILE_X, self.mouse_y % TILE_Y
self.offset_x += self.game.scroll_x % TILE_X # Add camera scroll to offset
self.offset_y += self.game.scroll_y % TILE_Y
# get the cell number
self.cell_x, self.cell_y = (self.mouse_x // TILE_X), (self.mouse_y // TILE_Y)
self.cell_x += int((self.game.scroll_x // TILE_X)) # Add camera scroll to cell
self.cell_y += int((self.game.scroll_y // TILE_Y))
# get the selected cell in iso grid
self.selected_x = (self.cell_y - ORIGIN_Y) + (self.cell_x - ORIGIN_X)
self.selected_y = (self.cell_y - ORIGIN_Y) - (self.cell_x - ORIGIN_X)
# height and width of a quarter of a tile, select the corner of the tile to nodge to a direction
h, w = TILE_Y / 2, TILE_X / 2
if self.offset_y < (h / w) * (w - self.offset_x):
self.selected_x -= 1
if self.offset_y > (h / w) * self.offset_x + h:
self.selected_y += 1
if self.offset_y < (h / w) * self.offset_x - h:
self.selected_y -= 1
if self.offset_y > (h / w) * (2 * w - self.offset_x) + h:
self.selected_x += 1
# translate the selected cell to world coordinate
self.selectedWorld_x, self.selectedWorld_y = self.game.to_screen(self.selected_x, self.selected_y)
def draw(self):
# Draw the selected tile with the camera scroll offset
self.game.screen.blit(self.image, (self.selectedWorld_x - self.game.scroll_x,
self.selectedWorld_y - self.game.scroll_y))
class SpriteSheet:
def __init__(self, image):
self.image = image
self.frames = []
def get_image(self):
for row in range(2):
for col in range(4):
if row == 0:
image = pygame.Surface((TILE_Y, TILE_Y / 2)).convert_alpha()
image.blit(self.image, (0, 0), (col * TILE_X / 2, row * TILE_Y / 2, TILE_X, TILE_Y))
image = pygame.transform.scale(image, (TILE_X, TILE_Y))
else:
image = pygame.Surface((TILE_Y, TILE_Y)).convert_alpha()
image.blit(self.image, (0, 0), (col * TILE_X / 2, row * TILE_Y / 2, TILE_X, TILE_Y * 2))
image = pygame.transform.scale(image, (TILE_X, TILE_Y * 2))
image.set_colorkey(WHITE)
self.frames.append(image)
return self.frames
# ------------------------- GAME LOOP ---------------------------- #
class Game:
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption(title)
self.clock = pygame.time.Clock()
pygame.key.set_repeat(400, 100)
self.debug = {}
self.sprite_sheet_image = pygame.image.load("isometric_whitebg - Copy.png")
self.index = 1
self.scroll_x, self.scroll_y = 0, 0
def new(self):
# initialize all variables and do all the setup for a new game
self.sprite_sheet = SpriteSheet(self.sprite_sheet_image)
self.tile_selected = self.sprite_sheet.get_image()[0]
self.tiles = self.sprite_sheet.get_image()
self.mouse_selection = MouseSelection(self, self.tile_selected)
self.camera = Camera(self, 1, 1)
def run(self):
# game loop - set self.playing = False to end the game
self.playing = True
while self.playing:
self.dt = self.clock.tick(FPS) / 1000
self.events()
self.update()
self.draw()
def quit(self):
pygame.quit()
sys.exit()
def update(self):
# update portion of the game loop
self.camera.update()
self.mouse_selection.update()
self.mx, self.my = pygame.mouse.get_pos()
# -------------------------------------------------- CAMERA SCROLLING ----------------------------------------#
if self.camera.x - self.scroll_x != WIDTH / 2:
self.scroll_x += (self.camera.x - (self.scroll_x + WIDTH / 2)) / 10
if self.camera.y - self.scroll_y != HEIGHT / 2:
self.scroll_y += (self.camera.y - (self.scroll_y + HEIGHT / 2)) / 10
# -------------------------------------------------- CAMERA SCROLLING ----------------------------------------#
self.debug_info()
def to_screen(self, x, y):
screen_x = (ORIGIN_X * TILE_X) + (x - y) * (TILE_X / 2)
screen_y = (ORIGIN_Y * TILE_Y) + (x + y) * (TILE_Y / 2)
return screen_x, screen_y
def draw_world(self):
for y in range(WORLD_Y):
for x in range(WORLD_X):
vWorld_x, vWorld_y = self.to_screen(x, y)
# Invisible tile
if self.index == 0:
self.screen.blit(self.tiles[1], (vWorld_x, vWorld_y))
# Grass
elif self.index == 1:
self.screen.blit(self.tiles[2], (vWorld_x - self.scroll_x, vWorld_y - self.scroll_y))
def draw(self):
self.screen.fill(BGCOLOUR)
self.draw_world()
self.mouse_selection.draw()
get_info(self.debug)
pygame.display.flip()
def debug_info(self):
self.debug["FPS"] = int(self.clock.get_fps())
self.debug["Cell"] = self.mouse_selection.cell_x, self.mouse_selection.cell_y
self.debug["Selected"] = int(self.mouse_selection.selected_x), int(self.mouse_selection.selected_y)
self.debug["Scroll"] = int(self.scroll_x), int(self.scroll_y)
self.debug["Mouse"] = int(self.mx), int(self.my)
self.debug["Mouse_offset"] = int(self.mouse_selection.offset_x), int(self.mouse_selection.offset_y)
def events(self):
# catch all events here
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
self.quit()
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
pass
game = Game()
while True:
game.new()
game.run()
Define the corner points of the map:
map_outline = [
pygame.math.Vector2(left_x, left_y),
pygame.math.Vector2(top_x, top_y),
pygame.math.Vector2(right_x, right_y,
pygame.math.Vector2(bottom_x, bottom_y)
]
With this information you can calculate the x and y axis of the map:
origin = map_outline[0]
x_axis = (map_outline[1] - map_outline[0]) / columns
y_axis = (map_outline[3] - map_outline[0]) / rows
You can use the x-axis and the y-axis to calculate a point in the map as a function of the row and column:
def transform(p, mat2x2):
x = p[0] * mat2x2[0][0] + p[1] * mat2x2[1][0]
y = p[0] * mat2x2[0][1] + p[1] * mat2x2[1][1]
return pygame.math.Vector2(x, y)
p_position = transform((column + 0.5, row + 0.5), (x_axis, y_axis)) + origin
If you want to get the row and column depending on the mouse cursor, you need to do the opposite. You need to calculate the inverse 2x2 matrix from the x and y axis. Using the inverse matrix, you can calculate the row and column as a function of a point on the map:
def inverseMat2x2(m):
a, b, c, d = m[0].x, m[0].y, m[1].x, m[1].y
det = 1 / (a*d - b*c)
return [(d*det, -b*det), (-c*det, a*det)]
m_pos = pygame.mouse.get_pos()
m_grid_pos = transform(pygame.math.Vector2(m_pos) - origin, point_to_grid)
m_col, m_row = int(m_grid_pos[0]), int(m_grid_pos[1])
Also see PyGameExamplesAndAnswers - Isometric
Minimal example:
replit.com/#Rabbid76/Pygame-IsometircMap
import pygame
pygame.init()
window = pygame.display.set_mode((500, 300))
clock = pygame.time.Clock()
colors = {'g': (40, 128, 40), 'd': (90, 60, 40)}
tilemap = [
'gdddg',
'dgddd',
'ggddg',
'ggddg',
'ddddg',
'dgggd'
]
columns, rows = len(tilemap[0]), len(tilemap)
isometric_tiles = {}
for key, color in colors.items():
tile_surf = pygame.Surface((50, 50), pygame.SRCALPHA)
tile_surf.fill(color)
tile_surf = pygame.transform.rotate(tile_surf, 45)
isometric_size = tile_surf.get_width()
tile_surf = pygame.transform.scale(tile_surf, (isometric_size, isometric_size//2))
isometric_tiles[key] = tile_surf
tile_size = (isometric_size, isometric_size//2)
def tileRect(column, row, tile_size):
x = (column + row) * tile_size[0] // 2
y = ((columns - column - 1) + row) * tile_size[1] // 2
return pygame.Rect(x, y, *tile_size)
game_map = pygame.Surface(((columns+rows) * isometric_size // 2, (columns+rows) * isometric_size // 4), pygame.SRCALPHA)
for column in range(columns):
for row in range(rows):
tile_surf = isometric_tiles[tilemap[row][column]]
tile_rect = tileRect(column, row, tile_size)
game_map.blit(tile_surf, tile_rect)
map_rect = game_map.get_rect(center = window.get_rect().center)
map_outline = [
pygame.math.Vector2(0, columns * isometric_size / 4),
pygame.math.Vector2(columns * isometric_size / 2, 0),
pygame.math.Vector2((columns+rows) * isometric_size // 2, rows * isometric_size / 4),
pygame.math.Vector2(rows * isometric_size / 2, (columns+rows) * isometric_size // 4)
]
for pt in map_outline:
pt += map_rect.topleft
origin = map_outline[0]
x_axis = (map_outline[1] - map_outline[0]) / columns
y_axis = (map_outline[3] - map_outline[0]) / rows
def inverseMat2x2(m):
a, b, c, d = m[0].x, m[0].y, m[1].x, m[1].y
det = 1 / (a*d - b*c)
return [(d*det, -b*det), (-c*det, a*det)]
point_to_grid = inverseMat2x2((x_axis, y_axis))
def transform(p, mat2x2):
x = p[0] * mat2x2[0][0] + p[1] * mat2x2[1][0]
y = p[0] * mat2x2[0][1] + p[1] * mat2x2[1][1]
return pygame.math.Vector2(x, y)
font = pygame.font.SysFont(None, 30)
textO = font.render("O", True, (255, 255, 255))
textX = font.render("X", True, (255, 0, 0))
textY = font.render("Y", True, (0, 255, 0))
p_col, p_row = 2, 2
run = True
while run:
clock.tick(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a and p_col > 0:
p_col -= 1
if event.key == pygame.K_d and p_col < columns-1:
p_col += 1
if event.key == pygame.K_w and p_row > 0:
p_row -= 1
if event.key == pygame.K_s and p_row < rows-1:
p_row += 1
p_position = transform((p_col + 0.5, p_row + 0.5), (x_axis, y_axis)) + origin
m_pos = pygame.mouse.get_pos()
m_grid_pos = transform(pygame.math.Vector2(m_pos) - origin, point_to_grid)
m_col, m_row = int(m_grid_pos[0]), int(m_grid_pos[1])
window.fill((0, 0, 0))
window.blit(game_map, map_rect)
pygame.draw.lines(window, (164, 164, 164), True, map_outline, 3)
pygame.draw.line(window, (255, 0, 0), origin, origin+x_axis, 3)
pygame.draw.line(window, (0, 255, 0), origin, origin+y_axis, 3)
pygame.draw.circle(window, (255, 255, 255), origin, 5)
pygame.draw.circle(window, (255, 0, 0), origin+x_axis, 5)
pygame.draw.circle(window, (0, 255, 0), origin+y_axis, 5)
window.blit(textO, textO.get_rect(topright = origin+(-5, 5)))
window.blit(textX, textX.get_rect(bottomright = origin+x_axis+(-5, -5)))
window.blit(textY, textX.get_rect(topright = origin+y_axis+(-5, 5)))
pygame.draw.ellipse(window, (255, 255, 0), (p_position[0]-16, p_position[1]-8, 32, 16))
if 0 <= m_grid_pos[0] < columns and 0 <= m_grid_pos[1] < rows:
tile_rect = tileRect(m_col, m_row, tile_size).move(map_rect.topleft)
pts = [tile_rect.midleft, tile_rect.midtop, tile_rect.midright, tile_rect.midbottom]
pygame.draw.lines(window, (255, 255, 255), True, pts, 4)
pygame.display.update()
pygame.quit()
exit()
this is my first post written here. With several tutorials and some advices got from here I created simple game.
Could someone please take a look on the code? Is there a better way to structure these function?
I know it looks messy but at least its working ;)
As it is my first game I really enjoy it. Here is my code
code in game.py file :
import sys
import pygame
from rocket import Rocket
class Game(object):
def __init__(self):
# configuration
self.tps_max = 100.0
# initialization
pygame.init()
self.screen = pygame.display.set_mode((1280, 720))
self.screen_rect = self.screen.get_rect()
self.tps_clock = pygame.time.Clock()
self.tps_delta = 0.0
self.player = Rocket(self)
game = True
while game is True:
# Handle events
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit(0)
elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
sys.exit(0)
# ticking
self.tps_delta += self.tps_clock.tick() / 1000.0
while self.tps_delta > 1 / self.tps_max:
self.tick()
self.tps_delta -= 1 / self.tps_max
# drawing
self.screen.fill((164, 222, 245))
self.draw()
pygame.display.flip()
def tick(self):
# check input
self.player.tick()
def draw(self):
self.player.draw()
if __name__ == "__main__":
Game()
Code in Rocket.py file:
import pygame
import random
import math
import sys
from pygame.math import Vector2
pygame.font.init()
font = pygame.font.Font(None, 30)
class Rocket(object):
def __init__(self, game):
self.game_over = False
self.game = game
size = self.game.screen.get_size()
self.speed = 3.0
self.wind_force = 0.2
self.wind_angle = random.randint(0, 359)
self.current_force = 0.1
self.current_angle = random.randint(0, 359)
self.random_change = 0
self.pos = Vector2(size[0] / 2, size[1] / 2)
self.vel = Vector2(0, 0)
self.acc = Vector2(0, 0)
# heading vector
self.heading = self.vel.angle_to(Vector2(0, 1))
self.angle_speed = 0
def addforce(self, force):
self.acc += force
def tick(self):
# Input
pressed = pygame.key.get_pressed()
if pressed[pygame.K_w]:
self.addforce(Vector2(0, -self.speed * 0.6).rotate(self.heading))
if pressed[pygame.K_s]:
self.addforce(Vector2(0, self.speed * 0.3).rotate(self.heading))
# self.addforce(Vector2(0, self.speed))
if pressed[pygame.K_d]:
self.addforce(Vector2(0, self.speed * 0.3).rotate(self.heading - 90))
if pressed[pygame.K_a]:
self.addforce(Vector2(0, self.speed * 0.3).rotate(self.heading + 90))
if pressed[pygame.K_q]:
self.angle_speed -= 1
if pressed[pygame.K_e]:
self.angle_speed += 1
# Physics
self.wind_angle = (self.wind_angle + random.randint(-2, 2)) % 360
self.wind_force += ((random.randint(-1, 2)) / 1000)
self.current_angle = (self.current_angle + 0.1 * random.randint(-1, 1)) % 360
self.current_force += ((random.randint(-1, 2)) / 1000)
self.vel *= 0.5
self.vel += Vector2(0, self.wind_force).rotate(self.wind_angle)
self.vel += Vector2(0, self.current_force).rotate(self.current_angle)
self.vel += self.acc
self.pos += self.vel
self.acc *= 0.5
self.angle_speed *= 0.5
self.heading = (self.heading + self.angle_speed) % 360
# offset
# check distance from centre to vessel pos
self.offset = math.hypot(((self.vel[0] - self.pos[0]) + 640), ((self.vel[1] - self.pos[1]) + 360))
# offset as 1
self.offset /= 750
# offset as accuracy in %
self.offset = int((1 - self.offset) * 100)
# gamer over to do
if self.offset < 0:
sys.exit(0)
else:
pass
def draw(self):
# base shape
vessel = [Vector2(5, 10), Vector2(-5, 10), Vector2(-5, -10), Vector2(0, -15), Vector2(5, -10)]
wind_arrow = [Vector2(0, 10), Vector2(0, 20), Vector2(20, 20), Vector2(20, 30), Vector2(30, 15), Vector2(20, 0),
Vector2(20, 10)]
current_arrow = [Vector2(0, 10), Vector2(0, 20), Vector2(20, 20), Vector2(20, 30), Vector2(30, 15),
Vector2(20, 0),
Vector2(20, 10)]
# rotating points
vessel = [p.rotate(self.heading) for p in vessel]
wind_arrow = [p.rotate(self.wind_angle + 90) for p in wind_arrow]
current_arrow = [p.rotate(self.current_angle + 90) for p in current_arrow]
# centered position & scale
vessel = [self.pos + p * 6 for p in vessel]
wind_arrow = [self.pos + p for p in wind_arrow]
current_arrow = [self.pos + p for p in current_arrow]
# draw shape
pygame.draw.polygon(self.game.screen, (255, 177, 10), vessel)
pygame.draw.polygon(self.game.screen, (233, 66, 245), wind_arrow)
pygame.draw.polygon(self.game.screen, (22, 57, 217), current_arrow)
def write(text, location, color=(0, 0, 0)):
self.game.screen.blit(font.render(text, True, color), location)
write(" Accuracy:" + str(self.offset), (20, 10))
write('Wind direction: ' + str(round(self.wind_angle)) + "deg . Wind force: " + str(
round((self.wind_force * 10), 2)), (20, 40))
write('Current direction: ' + str(round(self.current_angle)) + "deg . Current force: " + str(
round(self.current_force, 2)),
(20, 60))
# def writegameover(text, location, color=(0, 0, 0)):
# self.game.screen.blit(font.render(text, True, color), location)
# if self.game_over:
# writegameover(" GAME OVER", (200, 100))
I am pretty happy what I have, that was easier than I expected. More less I understand all the code. I am able to do minor modification, but I know my game is far away from being perfect.
Beside cleaning and optimalization, issue I can not handle is Game Over screen.
I don't know where place game_over method(). For now I have just set to quit game when game_over condition is met, but I want to display some game over screen with question "play again?" with some score. I know the best solution would be implement states Running, reset, game_over etc but its too complicated for me.
Could you please help me with this? Again, please understand this is my first python application, so any advices from you guys will be appreciated.
after some modification my rocket.py file still does not show Game over subtitle:
import pygame
import random
import math
import sys
from pygame.math import Vector2
pygame.font.init()
font = pygame.font.Font(None, 30)
class Rocket(object):
def __init__(self, game):
self.game_over = False
self.game = game
size = self.game.screen.get_size()
self.speed = 3.0
self.wind_force = 0.2
self.wind_angle = random.randint(0, 359)
self.current_force = 0.1
self.current_angle = random.randint(0, 359)
self.random_change = 0
self.pos = Vector2(size[0] / 2, size[1] / 2)
self.vel = Vector2(0, 0)
self.acc = Vector2(0, 0)
# heading vector
self.heading = self.vel.angle_to(Vector2(0, 1))
self.angle_speed = 0
def addforce(self, force):
self.acc += force
def tick(self):
# Input
pressed = pygame.key.get_pressed()
if pressed[pygame.K_w]:
self.addforce(Vector2(0, -self.speed * 0.6).rotate(self.heading))
if pressed[pygame.K_s]:
self.addforce(Vector2(0, self.speed * 0.3).rotate(self.heading))
# self.addforce(Vector2(0, self.speed))
if pressed[pygame.K_d]:
self.addforce(Vector2(0, self.speed * 0.3).rotate(self.heading - 90))
if pressed[pygame.K_a]:
self.addforce(Vector2(0, self.speed * 0.3).rotate(self.heading + 90))
if pressed[pygame.K_q]:
self.angle_speed -= 1
if pressed[pygame.K_e]:
self.angle_speed += 1
# Physics
self.wind_angle = (self.wind_angle + random.randint(-2, 2)) % 360
self.wind_force += ((random.randint(-1, 2)) / 1000)
self.current_angle = (self.current_angle + 0.1 * random.randint(-1, 1)) % 360
self.current_force += ((random.randint(-1, 2)) / 1000)
self.vel *= 0.5
self.vel += Vector2(0, self.wind_force).rotate(self.wind_angle)
self.vel += Vector2(0, self.current_force).rotate(self.current_angle)
self.vel += self.acc
self.pos += self.vel
self.acc *= 0.5
self.angle_speed *= 0.5
self.heading = (self.heading + self.angle_speed) % 360
# offset
# check distance from centre to vessel pos
self.offset = math.hypot(((self.vel[0] - self.pos[0]) + 640), ((self.vel[1] - self.pos[1]) + 360))
# offset as 1
self.offset /= 750
# offset as accuracy in %
self.offset = int((1 - self.offset) * 100)
# gamer over to do
if self.offset < 0:
# sys.exit(0)
self.writegameover(" GAME OVER:", (200, 100))
else:
pass
def draw(self):
# base shape
vessel = [Vector2(5, 10), Vector2(-5, 10), Vector2(-5, -10), Vector2(0, -15), Vector2(5, -10)]
wind_arrow = [Vector2(0, 10), Vector2(0, 20), Vector2(20, 20), Vector2(20, 30), Vector2(30, 15), Vector2(20, 0),
Vector2(20, 10)]
current_arrow = [Vector2(0, 10), Vector2(0, 20), Vector2(20, 20), Vector2(20, 30), Vector2(30, 15),
Vector2(20, 0),
Vector2(20, 10)]
# rotating points
vessel = [p.rotate(self.heading) for p in vessel]
wind_arrow = [p.rotate(self.wind_angle + 90) for p in wind_arrow]
current_arrow = [p.rotate(self.current_angle + 90) for p in current_arrow]
# centered position & scale
vessel = [self.pos + p * 6 for p in vessel]
wind_arrow = [self.pos + p for p in wind_arrow]
current_arrow = [self.pos + p for p in current_arrow]
# draw shape
pygame.draw.polygon(self.game.screen, (255, 177, 10), vessel)
pygame.draw.polygon(self.game.screen, (233, 66, 245), wind_arrow)
pygame.draw.polygon(self.game.screen, (22, 57, 217), current_arrow)
def write(text, location, color=(0, 0, 0)):
self.game.screen.blit(font.render(text, True, color), location)
write(" Accuracy:" + str(self.offset), (20, 10))
write('Wind direction: ' + str(round(self.wind_angle)) + "deg . Wind force: " + str(
round((self.wind_force * 10), 2)), (20, 40))
write('Current direction: ' + str(round(self.current_angle)) + "deg . Current force: " + str(
round(self.current_force, 2)),
(20, 60))
def writegameover(self, text, location, color=(0, 0, 0)):
self.game.screen.blit(font.render(text, True, color), location)
You can call writegameover() like this:
if self.offset < 0:
# sys.exit(0)
self.writegameover('GAME OVER', (200, 100), (0, 0, 0))
And then head down after the write() method
def writegameover(self, text, location, color=(0, 0, 0)):
# self.game.screen.blit(font.render(text, True, color), location)
print('over')
Note that the indentation of the writegameover() method should be the same as your draw() method
You will see now that when you go off the boundaries your program will print over continuously
Also I'm interested to know what's the goal of the game. Should I follow the blue or the pink arrow
game still doesn't display GAME OVER on screen.
game over condition:
if self.offset < 0:
self.writegameover(self, "GAME OVER", (200, 100))
pygame.time.delay(1000)
sys.exit(0)
writegameover function:
def writegameover(self, text, location, color=(0, 0, 0)):
self.game.screen.blit(font.render(text, True, color), location)
Time delay and exit works , for text display I get error: ValueError: invalid color argument.
If I specify color in arguments:
self.writegameover(self, "GAME OVER", (200, 100), (0,0,0)
I get:
TypeError: writegameover() takes from 3 to 4 positional arguments but 5 were given
I tried to do similiar to write function which working fine. For some reason writegameover has some issue with color.
In this program when the user types more text I want the rectangle to automatically get longer when the user types to keep the letters inside of the rectangle. However, it doesn't update the rectangle when the text gets longer. How do I fix this?
from pygame import *
init()
screen = display.set_mode((800, 600))
name_font = font.Font(None, 32)
name_text = ''
class Rectangle:
def __init__(self, x, y):
self.x = x
self.y = y
self.input_rect = Rect(x, y, 140, 32)
self.text_surface = name_font.render(name_text, True, (255, 255, 255))
color = Color('lightskyblue3')
draw.rect(screen, color, self.input_rect, 2)
self.input_rect.w = self.text_surface.get_width() + 10
screen.blit(self.text_surface, (self.input_rect.x + 5, self.input_rect.y + 5))
def naming():
global name_text
if events.type == KEYDOWN:
if keys[K_BACKSPACE]:
name_text = name_text[:-1]
screen.fill((0, 0, 0))
rect_1 = Rectangle(200, 200)
else:
name_text += events.unicode
while True:
rect_1 = Rectangle(200, 200)
for events in event.get():
keys = key.get_pressed()
naming()
if events.type == QUIT:
quit()
display.update()
time.delay(1)
The Rectangle.text_surface is a PyGame Surface. So you can easily get the precise width of the bounding box by simply calling self.text_surface.get_width().
But you start the size of the border-rect at 140, so this size has to be the maximum of 140 or whatever the new (longer) width is. Another problem is that when the rectangle re-sizes, the old rectangle is left behind. So whenever we now re-draw the rectangle, it erases the background to black.
This is all pretty easily encapsulated into the exiting __init__():
def __init__(self, x, y):
self.x = x
self.y = y
self.text_surface = name_font.render(name_text, True, (255, 255, 255))
rect_width = max( 140, 10 + self.text_surface.get_width() ) # Adjust the width
color = Color('lightskyblue3')
self.input_rect = Rect(x, y, rect_width, 32) # Use new width (if any)
draw.rect(screen, (0,0,0) , self.input_rect, 0) # Erase any existing rect
draw.rect(screen, color, self.input_rect, 2)
self.input_rect.w = self.text_surface.get_width() + 10
screen.blit(self.text_surface, (self.input_rect.x + 5, self.input_rect.y + 5))
I want that when I click on one of the possible squares an X is printed.
I have made a list of all the coordinates of the tic-tac-toe grid. I've also added the centre points of each of the rectangles coordinates. I'm trying to make that if I click within the area of one of the squares that the an X button shows up. The eventual aim is to make that a double-click results in a lodged result.
import matplotlib.pyplot as plt
import pygame
import sys
import pygame
pygame.font.init()
size = 320, 240
black = 0, 0, 0
white = 255,255,255
red = 255, 0, 0
x1y1 = [(100, 0), (100, 300)]
x2y2 = [(200, 0), (200, 300)]
x3y3 = [(0, 100), (300, 100)]
x4y4 = [(0, 200), (300, 200)]
def centroid(coord1, coord2):
xx = 50
yy = 50
coords = []
for a in range(0,3):
for b in range(0,3):
if a + 1 == int(coord1) and b + 1 == int(coord2):
coords += tuple([xx + a*100, yy + b*100])
return tuple(coords)
def fourCorners(a,b,length,width):
center = (a, b)
corner3 = (int(a + length/2), int(b + width/2))
corner2 = (int(a + length/2), int(b - width/2))
corner4 = (int(a - length/2), int(b + width/2))
corner1 = (int(a - length/2), int(b - width/2))
return [corner1 ,corner2 ,corner3 ,corner4]
def withinRect(a,b,corners):
if len(corners) != 4:
print('Pass a list parameter of length 4.')
elif int(corners[0][0]) >= int(a) >= int(corners[1][0]) and int(corners[0][1]) >= int(b) >= int(corners[1][1]):
return True
screen = pygame.display.set_mode((300,300))
screen.fill(white)
pygame.draw.line(screen, (0, 0, 255), x1y1[0], x1y1[1], 3)
pygame.draw.line(screen, (0, 0, 255), x2y2[0], x2y2[1], 3)
pygame.draw.line(screen, (0, 0, 255), x3y3[0], x3y3[1], 3)
pygame.draw.line(screen, (0, 0, 255), x4y4[0], x4y4[1], 3)
while True:
ev = pygame.event.get()
for event in ev:
# handle get_pressed
if event.type == pygame.MOUSEBUTTONUP:
pos = pygame.mouse.get_pos()
x, y = event.pos
v = fourCorners(centroid(1,1)[0],centroid(1,1)[1],100,100)
button = pygame.Rect(v[1][0], v[1][1] ,100,100)
if (withinRect(x,y,v) == True and button.collidepoint(event.pos)):
print('X')
pygame.display.flip()
else:
break
pygame.display.flip()
Traverse all the 9 fields by 2 nested loos and define a pygame.Rect for the corresponding field:
for a in range(3):
for b in range(3):
button = pygame.Rect(a*100, b*100, 100, 100)
If you want you can define a margin, to limit the area to the center of a field:
margin = 4
button = pygame.Rect(a*100+margin, b*100+margin, 100-2*margin, 100-2*margin)
Use colliderect() to check if the click was inside the area:
if button.collidepoint(pos):
# [...]
Draw a line from the .bottomleft to the .topright and a line from the .topleft to the .bottomright, to form a cross:
pygame.draw.line(screen, (0, 0, 255), button.bottomleft, button.topright, 3)
pygame.draw.line(screen, (0, 0, 255), button.topleft, button.bottomright, 3)
ev = pygame.event.get()
for event in ev:
if event.type == pygame.MOUSEBUTTONUP:
pos = pygame.mouse.get_pos()
margin = 4
for a in range(3):
for b in range(3):
button = pygame.Rect(a*100+margin, b*100+margin, 100-2*margin, 100-2*margin)
if button.collidepoint(pos):
pygame.draw.line(screen, (0, 0, 255), button.bottomleft, button.topright, 3)
pygame.draw.line(screen, (0, 0, 255), button.topleft, button.bottomright, 3)
I was writing the python/pygame code for Dice game. However, I have problem about Player's Points. My code can't calculate Player's Points correctly. I really need someone to fix this problem for me.
Here are the rules
Player's Points = 100 points
If Player's Points >= 10, Player's Points - 10 (Keep Playing)
If Player's Points < 10, "Game Over" (End Game)
Five of a Kind: Player's Points + 30
Four of a Kind: Player's Points + 20
Three of Kind: Player's Points + 10
Full House: Player's Points +15
Straight: Player's Points + 20
Two Pair: Player's Points + 5
No Winnings: Player's Points + 0
Here are my code:
gDieMain
#gDieMain.py
import pygame, sys# Imports pygame package, Imports system package
from pygame.locals import * # You will have namespace shortcuts
from gDieClass import gDie
from gDiebuttonClass import simpleButton
from random import *
pygame.init() # Initializes pygame for the program and computer
# Global Variables
PPOINTS = 100
DIENUM = 10
# Color Value
GREY = (128, 128, 128)
GREEN = (0, 100, 0)
LTGREEN = (0, 255, 0)
DKGREEN = (174, 177, 120)
WHITE = (255, 255, 255)
BLACK = (40, 40, 40)
RED = (201, 0, 22)
# Button Value
SIZE = 100
hbXsize = 130
hbYsize = 30
hbBut1XPOS = 85
hbBut2XPOS = 285
hbBut3XPOS = 485
hbBut4XPOS = 685
hbBut5XPOS = 885
hbButYPOS = 215
#Set up the window
DISPLAYWIDTH = 1125
DISPLAYHEIGHT = 600
DISPLAYSURF = pygame.display.set_mode((1200, 600))
pygame.display.set_caption('DICE GAME GRAPHICS')
BGCOLOR = (0, 128, 0)
DISPLAYSURF.fill(BGCOLOR)
# Set up the Player's Points (unfinished)
#PCOLOR = (40, 40, 40)
#POINTFONT = pygame.font.SysFont("Times New Roman", 65)
#PPFONT = pygame.font.SysFont("ScriptinaPro", 120)
#Button Layout
BUTTONWIDTH = 400
BUTTONHEIGHT = BUTTONWIDTH//7
BUTXPOS = (DISPLAYWIDTH - BUTTONWIDTH)//2
BUTYPOS = int(DISPLAYHEIGHT * .70)
HDISPLAYWIDTH = DISPLAYWIDTH//2
HDISPLAYHEIGHT = DISPLAYHEIGHT//2
CENTERBUTXPOS = HDISPLAYWIDTH - DISPLAYWIDTH//16
HSIZE = SIZE//2
GAP = (DISPLAYWIDTH//DIENUM - SIZE)//2
# pygame.font.SysFont()
# create a Font object from the system fonts
# SysFont(name, size, bold=False, italic=False) -> Font
myfont = pygame.font.SysFont("Times New Roman", 65)
#myfont1 = pygame.font.SysFont("Times New Roman", 65)
myfont2 = pygame.font.SysFont("Times New Roman", 35)
# Dice Layout
DIEYPOS = DISPLAYHEIGHT//4
DIE1XPOS = HDISPLAYWIDTH - HSIZE - 2 * GAP - 2 * SIZE
DIE2XPOS = HDISPLAYWIDTH - HSIZE - GAP - SIZE
DIE3XPOS = HDISPLAYWIDTH - HSIZE
DIE4XPOS = HDISPLAYWIDTH + HSIZE + GAP
DIE5XPOS = HDISPLAYWIDTH + HSIZE + 2 * GAP + SIZE
# Dice Position
position1 = (100, 100)
position2 = (300, 100)
position3 = (500, 100)
position4 = (700, 100)
position5 = (900, 100)
# Font Position
myfontPosition1 = (375, 20)
myfontPosition2 = (100, 500)
myfontPosition3 = (240, 260)
# Instantiate Objects
d1 = gDie(SIZE, position1)
d2 = gDie(SIZE, position2)
d3 = gDie(SIZE, position3)
d4 = gDie(SIZE, position4)
d5 = gDie(SIZE, position5)
#Make die object list
b1 = simpleButton(hbXsize, hbYsize, GREEN, LTGREEN, 'Dice 1',
DISPLAYSURF, (hbBut1XPOS, hbButYPOS))
b2 = simpleButton(hbXsize, hbYsize, GREEN, LTGREEN, 'Dice 2',
DISPLAYSURF, (hbBut2XPOS, hbButYPOS))
b3 = simpleButton(hbXsize, hbYsize, GREEN, LTGREEN, 'Dice 3',
DISPLAYSURF, (hbBut3XPOS, hbButYPOS))
b4 = simpleButton(hbXsize, hbYsize, GREEN, LTGREEN, 'Dice 4',
DISPLAYSURF, (hbBut4XPOS, hbButYPOS))
b5 = simpleButton(hbXsize, hbYsize, GREEN, LTGREEN, 'Dice 5',
DISPLAYSURF, (hbBut5XPOS, hbButYPOS))
# Instantiate Roll Buttons
firstRoll = simpleButton(BUTTONWIDTH, BUTTONHEIGHT, GREEN, LTGREEN,
'First Roll (10 pts)', DISPLAYSURF, (BUTXPOS, BUTYPOS))
secondRoll = simpleButton(BUTTONWIDTH, BUTTONHEIGHT, GREEN, LTGREEN,
'Second Roll', DISPLAYSURF, (BUTXPOS, BUTYPOS))
thirdRoll = simpleButton(BUTTONWIDTH, BUTTONHEIGHT, GREEN, LTGREEN,
'Last Roll', DISPLAYSURF, (BUTXPOS, BUTYPOS))
# Text label
#textLabel = simpleButton(600, BUTTONHEIGHT, DKGREEN, LTGREEN,
# '', DISPLAYSURF, (250, 300))
textLabel = simpleButton(600, BUTTONHEIGHT, BLACK, LTGREEN,
'', DISPLAYSURF, (250, 320))
# pygame.font.SysFont()
# create a Font object from the system fonts
# SysFont(name, size, bold=False, italic=False) -> Font
#myfont = pygame.font.SysFont("Sylfaen", 65)
# render text
# render()
# draw text on a new Surface
# render(text, antialias, color, background=None) -> Surface
#label = myfont.render("DICE POKER SIM!", 0, LTGREEN)
# Assign Objects Values
def setValue(dieList):
newDieList = []
for x in dieList:
if not x.get_hold():
dieNumber = randint(1, 6)
x.setValue(dieNumber)
newDieList.append(x.VALUE)
return newDieList
def displayAllDie(surf):
d1.displayDie(surf, position1[0], position1[1])
d2.displayDie(surf, position2[0], position2[1])
d3.displayDie(surf, position3[0], position3[1])
d4.displayDie(surf, position4[0], position4[1])
d5.displayDie(surf, position5[0], position5[1])
def displayButtons():
firstRoll.displayBut()
def displayHoldButtons():
b1.displayBut()
b2.displayBut()
b3.displayBut()
b4.displayBut()
b5.displayBut()
def score(dice):
global PPOINTS
counts = [0] * 7
for value in dice:
counts[value] += 1
if PPOINTS >= 10:
PPOINTS -= 10
if 5 in counts:
PPOINTS += 30
return "Five of a kind: ", "You win 30 points ", PPOINTS
elif 4 in counts:
PPOINTS += 20
return "Four of a kind: ", "You win 20 points ", PPOINTS
elif (3 in counts) and (2 in counts):
PPOINTS += 15
return "Full House: ", "You win 15 points ", PPOINTS
elif 3 in counts:
PPOINTS += 10
return "Three of Kind: ", "You win 10 points ", PPOINTS
elif not (2 in counts) and (counts[1] == 0 or
counts[6] == 0):
PPOINTS += 25
return "Straight: ", "You win 25 points ", PPOINTS
elif counts.count(2) == 2:
PPOINTS += 5
return "Two Pairs: ", "You win 5 points ", PPOINTS
else:
PPOINTS += 0
return "No winning: ", "You win 0 points ", PPOINTS
def stillText(dieList, surf):
a = setValue(dieList)
displayAllDie(surf)
return a
def allDieHold(dieList):
for x in dieList:
x.HOLD = False
def allDieHit(dieList):
for x in dieList:
x.HOLD = True
dieList = [d1, d2, d3, d4, d5]
setValue(dieList)
def main():
setValue(dieList)
displayButtons()
allDieHit(dieList)
allDieHold(dieList)
handresult = ""
handscore = ""
PPOINTS = ""
keepPlaying = True
while keepPlaying: #Main Game Loop
for event in pygame.event.get():
if event.type == QUIT: # Exit the game
pygame.quit()
sys.exit()
elif event.type == KEYDOWN: # Exit the game
if event.key == K_ESCAPE:
pygame.quit()
return
if event.type == MOUSEBUTTONDOWN:
mouseXY = pygame.mouse.get_pos()
if firstRoll.clicked(mouseXY):
firstRoll.display_HILIGHTED()
elif secondRoll.clicked(mouseXY):
secondRoll.display_HILIGHTED()
elif thirdRoll.clicked(mouseXY):
thirdRoll.display_HILIGHTED()
elif d1.clicked(mouseXY):
d1.switch_hold()
elif d2.clicked(mouseXY):
d2.switch_hold()
elif d3.clicked(mouseXY):
d3.switch_hold()
elif d4.clicked(mouseXY):
d4.switch_hold()
elif d5.clicked(mouseXY):
d5.switch_hold()
if event.type == MOUSEBUTTONUP:
if firstRoll.clicked(mouseXY):
DISPLAYSURF.fill(BGCOLOR)
setValue(dieList)
allDieHit(dieList)
allDieHold(dieList)
stillText(dieList, DISPLAYSURF)
secondRoll.displayBut()
firstRoll.inActive()
secondRoll.active()
#thirdRoll.inActive()
#displayHoldButtons()
elif secondRoll.clicked(mouseXY):
stillText(dieList, DISPLAYSURF)
thirdRoll.displayBut()
secondRoll.inActive()
thirdRoll.active()
elif thirdRoll.clicked(mouseXY):
a = stillText(dieList, DISPLAYSURF)
firstRoll.displayBut()
thirdRoll.inActive()
firstRoll.active()
handresult, handscore, PPOINTS= score(a)
print(score(a))
b1.displayBut()
b2.displayBut()
b3.displayBut()
b4.displayBut()
b5.displayBut()
textLabel.LABEL = handresult + str(handscore) + str(PPOINTS)
textLabel.displayBut()
DISPLAYSURF.blit(myfont.render('DICE GAME', True, LTGREEN), myfontPosition1)
#DISPLAYSURF.blit(myfont1.render("Player's Points: 100", True, LTGREEN), myfontPosition2)
DISPLAYSURF.blit(myfont2.render("Click on Dice: Red to Hold and White to Roll", True, LTGREEN), myfontPosition3)
# render()
# draw text on a new Surface
# render(text, antialias, color, background=None) -> Surface
displayAllDie(DISPLAYSURF)
pygame.display.update()
main()
gDieClass
#gDieClass.py
import pygame
from pygame.locals import *
class gDie:
#class that displays a grahical rep. of 6 sided die
def __init__(self, size, pos):
# Globals
#define some values
self.DIESURF = pygame.Surface((size, size), flags=SRCALPHA, depth=32)
self.DIESURF.fill((0, 0, 0, 0))
#Color
self.white = (255, 255, 255)
self.BLACK = (40, 40, 40)
self.RED = (201, 0, 22)
# Information about the Dice
self.POS = pos
self.HEIGHT = size
self.WIDTH = size
self.HOLD = False
self.VALUE = 0
#SIZE and RADIUS
self.SIZE = size
self.RADIUS = self.SIZE//10
HSIZE = self.SIZE//2
QSIZE = self.SIZE//4
#create Pips/Dots in standard places
self.POINT1 = (HSIZE, HSIZE)
self.POINT2 = (QSIZE, QSIZE)
self.POINT3 = (HSIZE + QSIZE, HSIZE + QSIZE)
self.POINT4 = (HSIZE + QSIZE, QSIZE)
self.POINT5 = (QSIZE, HSIZE + QSIZE)
self.POINT6 = (HSIZE + QSIZE, HSIZE)
self.POINT7 = (QSIZE, HSIZE)
def __drawBackground(self):
#create square with rounded corners for dice
if self.HOLD:
color = self.RED
else:
color = self.white
pygame.draw.circle(self.DIESURF, color, (self.RADIUS, self.RADIUS), self.RADIUS)
pygame.draw.circle(self.DIESURF, color, (self.SIZE - self.RADIUS, self.SIZE - self.RADIUS), self.RADIUS)
pygame.draw.circle(self.DIESURF, color, (self.SIZE - self.RADIUS, self.RADIUS), self.RADIUS)
pygame.draw.circle(self.DIESURF, color, (self.RADIUS, self.SIZE - self.RADIUS), self.RADIUS)
pygame.draw.rect(self.DIESURF, color, Rect((self.RADIUS, 0), (self.SIZE - (2 * self.RADIUS), self.SIZE)))
pygame.draw.rect(self.DIESURF, color, Rect((0, self.RADIUS), (self.SIZE, self.SIZE - (2 * self.RADIUS))))
def __makePip(self, point):
# function to make pips
if self.HOLD:
pygame.draw.circle(self.DIESURF, self.white, point, self.RADIUS)
else:
pygame.draw.circle(self.DIESURF, self.BLACK, point, self.RADIUS)
def switch_hold(self):
#self.HOLD = True
self.HOLD = not self.HOLD
return self.HOLD
def get_hold(self):
return self.HOLD
def clicked(self, MOUSEXY):
yesORno = False
P1 = self.POS
P2 = (P1[0] + self.WIDTH, P1[1] + self.HEIGHT)
yesORno = (P1[0] <= MOUSEXY[0] <= P2[0] and
P1[1] <= MOUSEXY[1] <= P2[1])
return yesORno
def setValue(self, value):
# create Die Background
self.__drawBackground()
self.VALUE = value
# create PIPs at value
if value == 1:
pip1 = self.__makePip(self.POINT1)
elif value == 2:
pip2 = self.__makePip(self.POINT2)
pip3 = self.__makePip(self.POINT3)
elif value == 3:
pip1 = self.__makePip(self.POINT1)
pip2 = self.__makePip(self.POINT2)
pip3 = self.__makePip(self.POINT3)
elif value == 4:
pip2 = self.__makePip(self.POINT2)
pip3 = self.__makePip(self.POINT3)
pip4 = self.__makePip(self.POINT4)
pip5 = self.__makePip(self.POINT5)
elif value == 5:
pip1 = self.__makePip(self.POINT1)
pip2 = self.__makePip(self.POINT2)
pip3 = self.__makePip(self.POINT3)
pip4 = self.__makePip(self.POINT4)
pip5 = self.__makePip(self.POINT5)
elif value == 6:
pip2 = self.__makePip(self.POINT2)
pip3 = self.__makePip(self.POINT3)
pip4 = self.__makePip(self.POINT4)
pip5 = self.__makePip(self.POINT5)
pip6 = self.__makePip(self.POINT6)
pip7 = self.__makePip(self.POINT7)
def displayDie(self, surf, x, y):
self.setValue(self.VALUE)
surf.blit(self.DIESURF, (x, y))
gDiebuttonClass
import pygame
from pygame.locals import *
class simpleButton:
# class that creates button objects
def __init__(self, width, height, color, textColor, label, surf, position):
# define and assign some self values
self.ACTIVE = True
self.HILIGHTED = False
self.LABEL = label
self.SURF = surf
self.POS = position
self.BUTCOLOR = color
self.TEXTCOLOR = textColor
# Generate a greyed-out version of color and a highlighted version of color
self.BUTGREYED = (color[0] * .25, color[1] * .25, color[2] * .25)
self.HIGHLIGHTCOLOR = (color[0] + ((255 - color[0])//2),
color[1] + ((255 - color[1])//2),
color[2] + ((255 - color[2])//2))
# Assign and calulate some size values
self.HEIGHT = height
self.WIDTH = width
self.HWIDTH = self.WIDTH//2
self.RADIUS = self.HEIGHT//2
self.THEIGHT = int(self.HEIGHT * .60)
# Create BUTTONSURF
self.BUTTONSURF = pygame.Surface((self.WIDTH, self.HEIGHT), flags=SRCALPHA, depth=32)
self.BUTTONSURF.fill((0, 0, 0, 0))
def __buttonBG(self, color): # draws the button shape
# Helper Method to create button background
# create square with rounded corners
pygame.draw.circle(self.BUTTONSURF, color, (self.RADIUS, self.RADIUS),
self.RADIUS)
pygame.draw.circle(self.BUTTONSURF, color,
(self.WIDTH - self.RADIUS, self.RADIUS), self.RADIUS)
pygame.draw.rect(self.BUTTONSURF, color,
Rect((self.RADIUS, 0), (self.WIDTH - 2 * self.RADIUS,
self.HEIGHT)))
def __buttonText(self): # places text surface on the button surface
# helper funtion to make text surface and blit on BUTTONSURF
# Set up the Font Object and how to Change Fonts
BUTFONT = pygame.font.SysFont("Sylfaen", self.THEIGHT)
# Render a Text Surface
self.TEXTSURF = BUTFONT.render(self.LABEL, True, self.TEXTCOLOR, None)
w, h = self.TEXTSURF.get_size()
XPOS = (self.WIDTH - w)//2
YPOS = (self.HEIGHT - h)//2
# Draw Text
self.BUTTONSURF.blit(self.TEXTSURF, (XPOS, YPOS))
def clicked(self, MOUSEXY):
yesORno = False
P1 = self.POS
P2 = (P1[0] + self.WIDTH, P1[1] + self.HEIGHT)
yesORno = (self.ACTIVE and P1[0] <= MOUSEXY[0] <= P2[0] and
P1[1] <= MOUSEXY[1] <= P2[1])
return yesORno
def active(self):
self.ACTIVE = True
return True
def inActive(self):
self.ACTIVE = False
return False
def changePos(self, X, Y):
self.POS = (X, Y)
return self.POS
def display_HILIGHTED(self):
self.__buttonBG(self.HIGHLIGHTCOLOR)
self.__buttonText()
self.SURF.blit(self.BUTTONSURF, self.POS)
def displayBut(self):
self.__buttonBG(self.BUTCOLOR)
self.__buttonText()
self.SURF.blit(self.BUTTONSURF, self.POS)
You call score(a) twice so points are added twice.
handresult, handscore, PPOINTS = score(a) # first time
print(score(a)) # second time
it should be
handresult, handscore, PPOINTS = score(a)
print(handresult, handscore, PPOINTS)