Simple delay counter in python not working - python

Hello I'm new to python and I'm trying to make a simple counter as a delay to blit some text in pygame so it does not show up instantly.
What I want to do is make text appear in a box when the player levels up.
def TEXT(A, B, C):
global ONE, TWO, THREE, FOUR
counter = 0
text = True
if text:
if counter == 10:
ONE = A
if counter == 20:
TWO = B
elif counter == 30:
THREE = C
elif counter == 40:
ONE = None
TWO = None
THREE = None
text = False
counter += 1
The code as a whole seems to be working fine but I just can't get the counter to work.
Here's the full program as reference:
from pygame import *
from userInterface import Title, Dead
WIN_WIDTH = 640
WIN_HEIGHT = 400
HALF_WIDTH = int(WIN_WIDTH / 2)
HALF_HEIGHT = int(WIN_HEIGHT / 2)
DISPLAY = (WIN_WIDTH, WIN_HEIGHT)
DEPTH = 32
FLAGS = 0
init()
screen = display.set_mode(DISPLAY, FLAGS, DEPTH)
saveState = False
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRAY = (30, 30, 30)
FONT = font.SysFont("Courier New", 15)
heroHP = 1000
hero={'name' : 'Hero',
'height':4,
'lvl': 1,
'xp' : 0,
'reward' : 0,
'lvlNext':25,
'stats': {'str' : 12, # strength
'dex' : 4, # dexterity
'int' : 15, # intelligence
'hp' : heroHP, # health
'atk' : [250,350]}} # range of attack values
boss1={'name' : 'Imp',
'xp' : 0,
'lvlNext':25,
'reward' : 25,
'stats': {'hp' :400,
'atk' : [300,350]}}
ONE = None
TWO = None
THREE = None
FOUR = None
def TEXT(A, B, C):
global ONE, TWO, THREE, FOUR
counter = 0
text = True
if text:
if counter == 0:
ONE = A
if counter == 10:
TWO = B
elif counter == 20:
THREE = C
elif counter == 30:
ONE = None
TWO = None
THREE = None
text = False
counter += 1
def level(char): # level up system
#nStr, nDex, nInt=0,0,0
while char['xp'] >= char['lvlNext']:
char['lvl']+=1
char['xp']=char['xp'] - char['lvlNext']
char['lvlNext'] = round(char['lvlNext']*1.5)
nStr=0.5*char['stats']['str']+1
nDex=0.5*char['stats']['dex']+1
nInt=0.5*char['stats']['int']+1
print(f'{char["name"]} levelled up to level {char["lvl"]}!') # current level
A = (f'{char["name"]} levelled up to level {char["lvl"]}!') # current level
print(f'( INT {round((char["stats"]["int"] + nInt))} - STR {round(char["stats"]["str"] + nStr)} - DEX {round(char["stats"]["dex"] + nDex)} )') # print new stats
B = (f'( INT {round((char["stats"]["int"] + nInt))} - STR {round(char["stats"]["str"] + nStr)} - DEX {round(char["stats"]["dex"] + nDex)} )') # print new statsm
char['stats']['str'] += nStr
char['stats']['dex'] += nDex
char['stats']['int'] += nInt
TEXT(A,B,None)
from random import randint
def takeDmg(attacker, defender): # damage alorithm
dmg = randint(attacker['stats']['atk'][0], attacker['stats']['atk'][1])
defender['stats']['hp'] = defender['stats']['hp'] - dmg
print(f'{defender["name"]} takes {dmg} damage!')
#TEXT(f'{defender["name"]} takes {dmg} damage!')
if defender['stats']['hp'] <= 0:
print(f'{defender["name"]} has been slain...')
#TEXT(f'{defender["name"]} has been slain...')
attacker['xp'] += defender['reward']
level(attacker)
if defender==hero:
#Dead()
pass
else:
hero['stats']['hp']=heroHP
#Title()
pass
def Battle(player, enemy):
global ONE, TWO, THREE, FOUR
mouse.set_visible(1)
clock = time.Clock()
YES = Rect(100, 100, 50, 50)
NO = Rect(500, 100, 50, 50)
Text = Rect(70, 300, 500, 75)
#while ((enemy['stats']['hp']) > 0):
while True:
for e in event.get():
if e.type == QUIT:
exit("Quit") # if X is pressed, exit program
elif e.type == KEYDOWN:
if e.key == K_ESCAPE:
exit()
elif e.type == MOUSEBUTTONDOWN:
# 1 is the left mouse button, 2 is middle, 3 is right.
if e.button == 1:
# `event.pos` is the mouse position.
if YES.collidepoint(e.pos):
takeDmg(player, enemy)
print(f'{enemy["name"]} takes the opportunity to attack!')
#TEXT(f'{enemy["name"]} takes the opportunity to attack!')
takeDmg(enemy, player)
elif NO.collidepoint(e.pos):
print(f'{enemy["name"]} takes the opportunity to attack!')
#TEXT(f'{enemy["name"]} takes the opportunity to attack!')
takeDmg(enemy, player)
screen.fill(WHITE)
draw.rect(screen, BLACK, YES)
draw.rect(screen, BLACK, NO)
draw.rect(screen, GRAY, Text)
YES_surf = FONT.render(("YES"), True, WHITE)
NO_surf = FONT.render(("NO"), True, WHITE)
Text1_surf = FONT.render(ONE, True, WHITE)
Text2_surf = FONT.render(TWO, True, WHITE)
Text3_surf = FONT.render(THREE, True, WHITE)
Text4_surf = FONT.render(FOUR, True, WHITE)
screen.blit(YES_surf, YES)
screen.blit(NO_surf, NO)
screen.blit(Text1_surf, (80, 305))
screen.blit(Text2_surf, (80, 320))
screen.blit(Text3_surf, (80, 335))
screen.blit(Text4_surf, (80, 350))
display.update()
clock.tick(60)
Battle(hero, boss1)

If all you want to do is make counter a global variable that only gets set to 0 at the start of the program instead of a local variable that gets reset to 0 on each call, you do that the exact same way you handled ONE and the other globals in the same function:
counter =0
def TEXT(A, B, C):
global ONE, TWO, THREE, FOUR
global counter
text = True
if text:
if counter == 10:
# etc.
counter += 1
The only changes are moving that counter = 0 from the function body to the top level, and adding global counter at the start of the function body.

Related

Changing Selected Variables Chosen From Input()

I want to change different variables in my code while it's running, for example changing the variable speed = 1 to speed = 2 using the CMD. The variable I want to change is decided on the person running the code through an input(). They type in speed, and the variable speed changes to another number, also chosen by the person running the code through another input().
To change the values, you should need to-
.
Press Enter, to pause the game
Select the CMD window
Type 'setvar', then Enter
Type 'speed', then Enter
Type '5', then Enter
.
I want this to change speed = 1 to speed = 5, but I also want to be able to do this with every variable, being able to change the score variable, or anything else. So far, I have made it so you input the variable you want to change, and what you want to change it to. The code is slightly messy, but readable.
So far I have tried
exec("%s = %s" % (var,setTo))
and
exec(f"{var} = '{setTo}'")
But it hasn't worked, although speed = 5 does.
The code I want help with is near the bottom. The whole code is...
def RUN():
import pygame
import time
import random
import msvcrt as m
pygame.init()
dis_width = 800
dis_height = 600
score = 0
x = 375
y = 275
foodx = -100
foody = -100
speed = 1
stanima = 0
gotox = 200
gotoy = 200
gotoSet = []
goto = []
gotoSet.append(gotox)
gotoSet.append(gotoy)
goto.append(gotoSet)
people = []
numOfPeople = 1 # Number of people
foodEaten = True
foodRun = True
speedRunPlus = True
speedRunMinus = True
runningRun = True
clock = pygame.time.Clock()
font = pygame.font.SysFont("Arial", 18)
dis = pygame.display.set_mode((dis_width, dis_height)) #screen stuff
pygame.display.set_caption('Game')
game_over = False
running = True
lightBlue = (50, 153, 213) #colors
red = (255, 100, 0)
yellow = (255, 255, 102)
blue = (70, 70, 255)
green1 = (0, 255, 0)
green2 = (0, 255, 25)
green3 = (0, 255, 50)
green4 = (0, 255, 75)
green5 = (0, 255, 100)
green6 = (0, 255, 125)
green7 = (0, 255, 150)
green8 = (0, 255, 175)
green9 = (0, 255, 200)
green10 = (0, 255, 225)
dis.fill(blue) #Backround
pygame.draw.rect(dis, lightBlue, [50, 50, 700, 500]) #Inner rectangle
def update_fps():
fps = str(int(clock.get_fps()))
fps = str("FPS: "+fps)
fps_text = font.render(fps, 1, pygame.Color("coral"))
return fps_text
def speedRender():
speed_str = str(speed)
speed_sentance = str("Average Speed: "+speed_str)
speed_text = font.render(speed_sentance, 1, pygame.Color("coral"))
return speed_text
def player(x, y, color, stamina): #Rectangle player
player = pygame.draw.rect(dis, color, [x, y, 25, 25])
if stanima == 1:
pygame.draw.rect(dis, red, [x+11, y+11, 3, 3])
elif stanima == 2:
pygame.draw.rect(dis, red, [x+10, y+10, 5, 5])
elif stanima == 3:
pygame.draw.rect(dis, red, [x+9, y+9, 7, 7])
elif stanima == 4:
pygame.draw.rect(dis, red, [x+8, y+8, 9, 9])
elif stanima == 5:
pygame.draw.rect(dis, red, [x+7, y+7, 11, 11])
elif stanima == 6:
pygame.draw.rect(dis, red, [x+6, y+6, 13, 13])
elif stanima == 7:
pygame.draw.rect(dis, red, [x+5, y+5, 15, 15])
elif stanima == 8:
pygame.draw.rect(dis, red, [x+4, y+4, 17, 17])
elif stanima == 9:
pygame.draw.rect(dis, red, [x+3, y+3, 19, 19])
def food(foodx, foody): #Rectangle food
food = pygame.draw.rect(dis, yellow, [foodx, foody, 10, 10])
for num1 in range(numOfPeople):
x = random.randint(300,400)
y = random.randint(300,400)
person = []
person.append(x)
person.append(y)
person.append(1)
person.append(goto)
person.append(score)
people.append(person)
while not game_over:
while running:
dis.fill(blue)
pygame.draw.rect(dis, lightBlue, [50, 50, 700, 500])
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
game_over = True
for num2 in range(numOfPeople):
x = people[0][0]
y = people[0][1]
#speed = people[0][2]
goto = people[0][3]
score = people[0][4]
del people[0]
if x+12 > foodx+5: # "AI"
x -= speed
elif x+12 < foodx+5:
x += speed
if y+12 > foody+5: # "AI"
y -= speed
elif y+12 < foody+5:
y += speed
if x > 725: #Creates Borders
x = 725
game_over = True
elif x < 50:
x = 50
game_over = True
if y > 525:
y = 525
game_over = True
elif y < 50:
y = 50
game_over = True
if x >= foodx-24 and x <= foodx+10:
if y >= foody-24 and y <= foody+10:
score += 1
foodEaten = True
#print("Score:", score)
person = []
person.append(x)
person.append(y)
person.append(1)
person.append(goto)
person.append(score)
people.append(person)
playerColor = green1
player(x, y, playerColor, stanima) #Creating Player
if foodEaten == True:
foodx = random.randint(90, 700)
foody = random.randint(90, 500)
stanima += 1
foodEaten = False
food(foodx, foody) #Creating Food
pressed = pygame.key.get_pressed() #Key Movement
if pressed[pygame.K_RCTRL]:
dis.blit(update_fps(), (10,0))
dis.blit(speedRender(), (100,0))
if pressed[pygame.K_SPACE]:
RUN()
if pressed[pygame.K_ESCAPE]:
running = False
game_over = True
if pressed[pygame.K_RSHIFT]:
if foodRun == True:
foodx = random.randint(90, 700)
foody = random.randint(90, 500)
stanima += 1
foodEaten = False
foodRun = False
else:
foodRun = True
if pressed[pygame.K_RETURN]:
if runningRun == True:
running = False
runningRun = False
print(" ")
else:
runningRun = True
if pressed[pygame.K_MINUS]:
if speedRunMinus == True:
speed -= 0.1
speedRunMinus = False
else:
speedRunMinus = True
if pressed[pygame.K_EQUALS]:
if speedRunPlus == True:
speed += 0.1
speedRunPlus = False
else:
speedRunPlus = True
pygame.display.flip() #updating screen
clock.tick()
if not game_over:
command = input(" :")
commandSplit = command.split(".")
#try:
if commandSplit[0] == "return":
var = input(" :")
if var in dir():
print(" :", eval(var), sep='')
else:
print(" :Variable Not Found")
elif commandSplit[0] == "run":
if commandSplit[1] == "exit":
running = False
game_over = True
elif commandSplit[0] == "setvar":
var = input(" :")
print("Var value now:", eval(var), sep='')
if var in locals():
setTo = input("Change variable to:") #Code I need help with -----------------------
print("Var value after:", eval(var), sep='')
else:
print(" :Invalid Syntax Error")
'''
except Exception:
print(" :Invalid Syntax Error")
pass
'''#to implement later
RUN()

issues with checking if my images collided in pygame [duplicate]

This question already has an answer here:
Why is my collision test always returning 'true' and why is the position of the rectangle of the image always wrong (0, 0)?
(1 answer)
Closed 1 year ago.
So I'm trying to check im my bird images are touching my could images and if they are to print print('Collided1!').
My Issue is that print('Collided1!') goes off no matter what and is not checking whether the images are touching. colliderect was the solution I found online but I don't seem to know how it works because this is not working.
Do You Know how to fix this? and check whether my images are touching or not?
from random import randint
import pygame, sys
import random
import time
pygame.init()
pygame.display.set_caption('Lokaverkefni')
DISPLAYSURF = pygame.display.set_mode((1224, 724))
fpsClock = pygame.time.Clock()
FPS = 60
a = 1
b = 1
c = 15
x = 100
y = 480
start = 0
score = 0
landX = 1205
totalScore = 0
level = 'low'
directionForBird = 'none'
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
BASICFONT = pygame.font.Font('freesansbold.ttf', 30)
background_resized = pygame.image.load('sky.jpg')
background = pygame.transform.scale(background_resized, (1224, 724))
bird1 = pygame.image.load('bird1.png')
bird1_resized = pygame.transform.scale(bird1, (170, 150))
bird1Surface = bird1_resized.get_rect()
bird2 = pygame.image.load('bird2.png')
bird2_resized = pygame.transform.scale(bird2, (170, 150))
bird2Surface = bird2_resized.get_rect()
cloudsList = ['cloud1.png', 'cloud2.png', 'cloud3.png', 'cloud4.png']
clouds = random.choice(cloudsList)
cloud = pygame.image.load(clouds)
cloud_resized = pygame.transform.scale(cloud, (352, 352))
cloudSurface = cloud_resized.get_rect()
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if level == 'low':
if (event.key == K_SPACE ):
directionForBird = 'up'
level = 'high'
FPS += 2
c += 1
if directionForBird == 'up':
y -= 10
if y == 10:
directionForBird = 'down'
if directionForBird == 'down':
y += 10
if y == 480:
directionForBird = 'none'
if a == 1:
DISPLAYSURF.blit(background, (0, 0))
DISPLAYSURF.blit(bird1_resized, (x, y))
DISPLAYSURF.blit(cloud_resized, (landX, 300))
b += 1
if b == c:
a += 1
if a == 2:
DISPLAYSURF.blit(background, (0, 0))
DISPLAYSURF.blit(bird2_resized, (x, y))
DISPLAYSURF.blit(cloud_resized, (landX, 300))
b -= 1
if b == 1:
a -= 1
start += 1
if start == 100:
start -= 1
directionForLand = 'left'
if directionForLand == 'left':
landX -= 15
if landX == -550:
landX = 1205
level = 'low'
clouds = random.choice(cloudsList)
cloud = pygame.image.load(clouds)
cloud_resized = pygame.transform.scale(cloud, (352, 352))
score += 1
if score == 30:
score = 0
totalScore += 1
scoreText = BASICFONT.render('Stig : %s' % (totalScore), True, (BLACK))
scoreRect = scoreText.get_rect()
scoreRect.topleft = (1070, 10)
DISPLAYSURF.blit(scoreText, scoreRect)
# This is Supossed to Be what checks if the bird images
# colide with the cloud images
if bird1Surface.colliderect(cloudSurface):
print('Collided1!')
if bird2Surface.colliderect(cloudSurface):
print('Collided1!')
pygame.display.update()
fpsClock.tick(FPS)
bird1Surface, bird2Surface and cloudSurface always have an upper left of (0,0), so they are always on top of each other.. You don't change the rectangles when you move the birds. You need to track the bird x,y and the cloud x,y, and construct new rectangles with the current x,y and the known width and height before you do the collision check.

Why will this loop not repeat itself in the order of the statements?

I am having trouble sorting out a loop in my program which does not behave a I would expect. This program lets you play "Connect Four". I included the full (runnable code) and the excerpt that troubles me at the end.
import numpy as np
import random
import pygame
import time
BOARD_SIZE = 6
BOARD_BOX_NUM = BOARD_SIZE ** 2
GIVEN_IDS = 0
# ------------------------------- setting up pygame --------------------------------------------
pygame.init()
display_height = 600
display_width = 600
game_display = pygame.display.set_mode((display_width, display_height))
clock = pygame.time.Clock()
# ------------------------------- colours ----------------------------------------------------
white = (255, 255, 255)
black = (0, 0, 0)
blue = (0,0,255)
light_blue = (30, 144, 255)
red = (200, 0, 0)
light_red = (255, 0, 0)
yellow = (200, 200, 0)
light_yellow = (255, 255, 0)
green = (34, 177, 76)
light_green = (0, 255, 0)
# ------------------------------- methods for the game algorythm ------------------------------
def rolling_window(a, size):
# This method is required for the algorythm that broadcasts the board for a win
shape = a.shape[:-1] + (a.shape[-1] - size + 1, size)
strides = a.strides + (a. strides[-1],)
return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)
class Chip:
def __init__(self, colour):
if colour == "Blue":
self.colour = colour
if colour == "Red":
self.colour = colour
global GIVEN_IDS
self.iD = GIVEN_IDS
GIVEN_IDS += 1
def get_iD(self):
return self.iD
class Game:
def __init__(self, player_colour="Blue", comp_colour="Red"):
self.board = np.empty(BOARD_BOX_NUM, dtype=Chip)
self.board = self.board.reshape(BOARD_SIZE, BOARD_SIZE)
self.player_colour = player_colour
self.comp_colour = comp_colour
def get_comp_colour(self):
return self.comp_colour
def get_player_colour(self):
return self.player_colour
def give_str_board(self):
"""Returns a copy of the board array and replaces the Chip objects with the str with the colour of the chips."""
this_board = np.copy(self.board)
for x, y in np.ndindex(this_board.shape):
if this_board[x, y] is not None:
if this_board[x, y].colour == "Blue":
this_board[x, y] = "Blue"
else:
this_board[x, y] = "Red"
return this_board
def print_board_in_console(self):
"""This function holds the board which is a 8x8 matrix."""
this_board = self.give_str_board()
print(this_board)
print("-"*40)
def insert_chip(self, chip, col):
"""Method for making a new entry to the board. For the player and enemy.
The column has to be parametrised in the pythonic way. i.e. cols from 0-7."""
# slices the entries of the column into a new array
col_entries = self.board[:, col:col+1]
# checks for all unoccupied pos in this column(entries are None)
# double array of indexes with the form (array([row_i, ...]), array([column_i, ...]))
# checking the condition with "is" is here not possible, because "is" operator cannot be overloaded
none_indexes = np.where(col_entries == None)
# check whether the column cannot contain an extra chip and function has to be aborted
if len(none_indexes[0]) == 0:
print("This column is full. Chose again.")
return False
# the pos where the chip will fall is the one with the highest index
self.board[len(none_indexes[0]) - 1, col] = chip
return True
def get_chip(self, x, y):
"""This function can return the information about a chip in a pos of the board."""
chip = self.board[x, y]
return chip
def is_won(self):
"""This function can be used to check the board on whether the game has been decided.
The function differentiates between player and enemy and returns..."""
winning_chip = None
# get a copy of the board which only contains str and None
this_board = self.give_str_board()
flipped_board = np.fliplr(this_board)
# in order to check the entire board for 4 Chips in a formation individual rows and cols are examined
# use for loops to isolate rows and cols
for this_ax in range(0, 2):
for index in range(0, BOARD_SIZE):
# the stack will contain the row[index] when this_ax = 0 and the col[index] when this_ax = 1
stack = this_board.take(index, axis=this_ax)
# this will be the patterns, that are searched for
winning_formations = [['Blue', 'Blue', 'Blue', 'Blue'], ['Red', 'Red', 'Red', 'Red']]
for i in winning_formations:
bool_array = rolling_window(stack, 4) == i
if [True, True, True, True] in bool_array.tolist():
# the stack_index is the index of the first chip in the 4xChip formation in the row/col
stack_index_tuple, = np.where(np.all(bool_array == [True, True, True, True], axis=1))
stack_index = stack_index_tuple[0]
loop_index = index
# this_ax = 0 means loop_index is row and stack_index is col
if this_ax == 0:
winning_chip = self.get_chip(loop_index, stack_index)
break
else:
winning_chip = self.get_chip(stack_index, loop_index)
break
# This next part of the algorythm checks whether diagonal patterns of the array
# contain a winning formation
# if this bit is problematic: change the 0 in range()!!!
for index in range(0, BOARD_SIZE - 2):
for board in [this_board, flipped_board]:
diag_elements = board.diagonal(index)
for i in winning_formations:
bool_array = rolling_window(diag_elements, 4) == i
if [True, True, True, True] in bool_array.tolist():
# the stack_index is the index of the first chip in the 4xChip formation in the row/col
diag_el_index_tuple, = np.where(
np.all(bool_array == [True, True, True, True], axis=1))
diag_index = diag_el_index_tuple[0]
loop_index = index
# this_ax = 0 means loop_index is row and stack_index is col
if board == this_board:
winning_chip = self.get_chip(loop_index, diag_index)
break
else:
winning_chip = self.get_chip(diag_index, loop_index)
break
if winning_chip is not None:
return winning_chip.colour
return None
def get_comp_move(self):
"""This method generates the computer's move (the column) based on INTELLIGENCE!!!!
Returns the column of the move"""
c_colour = self.get_comp_colour()
p_colour = self.get_player_colour()
# check, if the comp can win in the next move
for i in range(0, BOARD_SIZE):
board = self.give_str_board()
chip = Chip(c_colour)
self.insert_chip(chip, i)
if self.is_won() == c_colour:
return i
# check, if the player can win in the next move and block that position
for i in range(0, BOARD_SIZE):
board = self.give_str_board()
chip = Chip(p_colour)
self.insert_chip(chip, i)
if self.is_won() == p_colour:
return i
# accumulate preferable positions for the next move
good_spots = []
board = self.give_str_board()
for axis in range(0, 2):
for index in range(0, BOARD_SIZE):
# the stack will contain the row[index] when this_ax = 0 and the col[index] when this_ax = 1
stack = board.take(index, axis=axis)
# this will be the patterns, that are searched for
for i in [c_colour, c_colour]:
bool_array = rolling_window(stack, 2) == i
if [True, True] in bool_array.tolist():
# the stack_index is the index of the first chip in the 4xChip formation in the row/col
stack_index_tuple, = np.where(np.all(bool_array == [True, True], axis=1))
stack_index = stack_index_tuple[0]
# this_ax = 0 means loop_index is row and stack_index is col
if axis == 0:
# "- 1" because this if-statement is called when broadcasting a row. i.e. column before
good_spots.append(stack_index - 1)
else:
good_spots.append(index)
# The pick is the x-coo of the first of a series of two chips (column) or the x before (row).
print(good_spots)
pick = random.randint(0, len(good_spots))
return pick
# make a move, "better than nothing"
flag = True
while flag is True:
rnd = random.randint(0, BOARD_SIZE)
if self.board[rnd, 0] is None:
return rnd
# ------------------------------- this part will take care of the visualisation in pygame ------------------------
# buttons = []
#
# def button(self, text, x, y, radius, inactive_colour, active_colour, action=None, size=" "):
# cur = pygame.mouse.get_pos()
# if x + radius > cur[0] > x - radius and y + radius > cur[1] > y - radius:
# pygame.draw.circle(game_display, active_colour, (x, y), radius)
#
# ix = None
# iy = None
# for event in pygame.event.get():
# if event.type == pygame.MOUSEBUTTONDOWN:
# ix, iy = event.pos
#
# if ix is not None and iy is not None:
# if x + radius > ix > x - radius and y + radius > iy > y - radius and action is not None:
# if action == "quit":
# pygame.quit()
# quit()
#
# if action == "move":
# col = int(x / 80 - 90)
# self.insert_chip(Chip(self.get_player_colour()), col)
# else:
# pygame.draw.circle(game_display, inactive_colour, (x, y), radius)
def draw_board(self):
board = self.give_str_board()
pygame.draw.rect(game_display, green, (60, 60, 80*BOARD_SIZE, 80*BOARD_SIZE))
for y in range(0, BOARD_SIZE):
for x in range(0, BOARD_SIZE):
dx = 90 + x * 80
dy = 90 + y * 80
if board[x, y] is None:
pygame.draw.circle(game_display, white, (dy, dx), 30)
elif board[x, y] == "Blue":
pygame.draw.circle(game_display, blue, (dy, dx), 30)
elif board[x, y] == "Red":
pygame.draw.circle(game_display, red, (dy, dx), 30)
# draw the selector square
pygame.draw.rect(game_display, yellow, (self.selector_pos * 80 + 80, 60, 20, 20))
selector_pos = 0
def move_selector(self, dir):
selector_pos = self.selector_pos
if dir == 'left' and selector_pos >= 0:
new_x = selector_pos * 80 - 80
pygame.draw.rect(game_display, yellow, (new_x, 60, 20, 20))
self.selector_pos -= 1
if dir == 'right' and selector_pos <= BOARD_SIZE - 1:
new_x = selector_pos * 80 + 80
pygame.draw.rect(game_display, yellow, (new_x, 60, 20, 20))
self.selector_pos += 1
def intro(self):
return
def game_loop(self, comp_goes_first=False):
game_over = False
while game_over is not True:
# here comes the computer's move
if comp_goes_first is True:
col = self.get_comp_move()
chip = Chip(self.get_comp_colour())
self.insert_chip(chip, col)
# This will be the player move
move_over = False
while move_over is not True:
for event in pygame.event.get():
print(event)
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
self.move_selector('right')
pygame.draw.rect(game_display, yellow, (50, 50, 50, 50))
if event.key == pygame.K_LEFT:
self.move_selector('left')
if event.key == pygame.K_RETURN:
# the selector position indicates the column which the player has chosen.
col = self.selector_pos
chip = Chip(self.get_player_colour())
move_over = self.insert_chip(chip, col)
game_display.fill(white)
self.draw_board()
pygame.display.update()
comp_goes_first = True
clock.tick(15)
game = Game()
game.game_loop()
Now to the part that particularly leaves me in doubt.
As the following loop runs, I can make the Player's move in the game as expected with the use of arrow keys and return, however then the program goes crazy. It will do multiple moves for the computer and sometimes the player as well. This is a picture of the GUI after the loop has run once (player's move and then the computer's move and now it would be the players move again).
At this point I am wondering whether I got something fundamentally wrong with the while loop construction here and I cannot figure it out. What is the issue?
game_over = False
while game_over is not True:
# here comes the computer's move
if comp_goes_first is True:
col = self.get_comp_move()
chip = Chip(self.get_comp_colour())
self.insert_chip(chip, col)
# This will be the player move
move_over = False
while move_over is not True:
for event in pygame.event.get():
print(event)
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
self.move_selector('right')
if event.key == pygame.K_LEFT:
self.move_selector('left')
if event.key == pygame.K_RETURN:
# the selector position indicates the column which the player has chosen.
col = self.selector_pos
chip = Chip(self.get_player_colour())
move_over = self.insert_chip(chip, col)
game_display.fill(white)
self.draw_board()
pygame.display.update()
comp_goes_first = True
clock.tick(15)
Your problem looks to me to be in your AI logic. You're making a copy of the board for the AI to experiment on, but then you're not using it, and instead inserting chips into the real board.
# check, if the comp can win in the next move
for i in range(0, BOARD_SIZE):
# Never used.
board = self.give_str_board()
chip = Chip(c_colour)
# inserting onto the real board.
self.insert_chip(chip, i)
print("insert check", board, self)
if self.is_won() == c_colour:
return i

How to fade from one colour to another in pygame?

How would I fade from one colour into another in pygame? I want to slowly change the colour of a circle from green to blue to purple to pink to red to orange to yellow to green. How would I do that? At the moment, I'm using
def colour():
switcher = {
0: 0x2FD596,
1: 0x2FC3D5,
2: 0x2F6BD5,
3: 0x432FD5,
4: 0x702FD5,
5: 0xBC2FD5,
6: 0xD52F91,
7: 0xD52F43,
8: 0xD57F2F,
9: 0xD5D52F,
10: 0x64D52F,
11: 0x2FD557,
}
return switcher.get(round((datetime.datetime.now() - starting_time).total_seconds()%11))
but that has really big steps in between the colours and looks clunky.
The key is to simply calculate how much you have to change each channel (a,r,g and b) each step. Pygame's Color class is quite handy, since it allows iteration over each channel and it's flexible in it's input, so you could just change e.g. 'blue' to 0x2FD596 in the below example and it will still run.
Here's the simple, running example:
import pygame
import itertools
pygame.init()
screen = pygame.display.set_mode((800, 600))
colors = itertools.cycle(['green', 'blue', 'purple', 'pink', 'red', 'orange'])
clock = pygame.time.Clock()
base_color = next(colors)
next_color = next(colors)
current_color = base_color
FPS = 60
change_every_x_seconds = 3.
number_of_steps = change_every_x_seconds * FPS
step = 1
font = pygame.font.SysFont('Arial', 50)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
text = font.render('fading {a} to {b}'.format(a=base_color, b=next_color), True, pygame.color.Color('black'))
step += 1
if step < number_of_steps:
# (y-x)/number_of_steps calculates the amount of change per step required to
# fade one channel of the old color to the new color
# We multiply it with the current step counter
current_color = [x + (((y-x)/number_of_steps)*step) for x, y in zip(pygame.color.Color(base_color), pygame.color.Color(next_color))]
else:
step = 1
base_color = next_color
next_color = next(colors)
screen.fill(pygame.color.Color('white'))
pygame.draw.circle(screen, current_color, screen.get_rect().center, 100)
screen.blit(text, (230, 100))
pygame.display.update()
clock.tick(FPS)
If you don't want to be dependent on the framerate but rather use a time based approach, you could change the code to:
...
change_every_x_milliseconds = 3000.
step = 0
running = True
while running:
...
if step < change_every_x_milliseconds:
current_color = [x + (((y-x)/change_every_x_milliseconds)*step) for x, y in zip(pygame.color.Color(base_color), pygame.color.Color(next_color))]
else:
...
...
pygame.display.update()
step += clock.tick(60)
You could go between all the values from one colour to the next by converting it into an int, increasing the number, and converting it back to hex. Then you just loop until you reach the next value with something like so:
value1 = 0xff00ff
value2 = 0xffffff
increment = 1 # amount to decrease or increase the hex value by
while value1 != value2:
if value1 > value2:
if int(value1)-increment < int(value2): # failsafe if the increment is greater than 1 and it skips being the value
value1 = value2
else:
value1 = hex(int(value1)-increment)
else:
if int(value1)+increment > int(value2):
value1 = value2
else:
value1 = hex(int(value1)+increment)
code_to_change_colour(value1)
See the edit by Prune for a much more elegant implementation of this. Note that code_to_change_colour(value1) should be changed to however you change the colour in your program. The increment will let you change how many colours are skipped. Obviously this code would need to be edited into a manner it can be used easily: e.g a function like def fade(value1, value2).
Edit from #Prune -- because code doesn't work well in comments.
Note that most of what you've written is "merely" loop control. You have known start and stop values and a fixed increment. This suggests a for loop rather than a while. Consider this:
value1 = int(0xff00ff)
value2 = int(0xffffff)
increment = 1 if value1 < value2 else -1
for current in range(value1, value2, increment):
code_to_change_colour(hex(value1))
value1 = value2
If you'd prefer just calculating the colors (without using any surfaces), you can do this:
First, you need to determine how long you want the dissolve to take. You also need to store the original and final colors. Last, calculate the blend. I would create a class for this:
import pygame
import time
class color_blend:
def __init__(self, start_color, end_color, duration=1000):
self.start_color = pygame.Color(start_color.r, start_color.g, start_color.b)
self.current_color = pygame.Color(start_color.r, start_color.g, start_color.b)
self.end_color = end_color
self.duration = float(duration)
self.start_time = color_blend.millis()
# Return current time in ms
#staticmethod
def millis():
return (int)(round(time.time() * 1000))
# Blend any 2 colors
# 0 <= amount <= 1 (0 is all initial_color, 1 is all final_color)
#staticmethod
def blend_colors(initial_color, final_color, amount):
# Calc how much to add or subtract from start color
r_diff = (final_color.r - initial_color.r) * amount
g_diff = (final_color.g - initial_color.g) * amount
b_diff = (final_color.b - initial_color.b) * amount
# Create and return new color
return pygame.Color((int)(round(initial_color.r + r_diff)),
(int)(round(initial_color.g + g_diff)),
(int)(round(initial_color.b + b_diff)))
def get_next_color(self):
# Elapsed time in ms
elapsed_ms = color_blend.millis() - self.start_time
# Calculate percentage done (0 <= pcnt_done <= 1)
pcnt_done = min(1.0, elapsed_ms / self.duration)
# Store new color
self.current_color = color_blend.blend_colors(self.start_color, self.end_color, pcnt_done)
return self.current_color
def is_finished(self):
return self.current_color == self.end_color
# Blend red to green in .3 seconds
c = color_blend(pygame.Color(255, 0, 0), pygame.Color(0, 255, 0), 300)
while not c.is_finished():
print(c.get_next_color())
You can easily modify this to do non-linear blending. For example, in blend_colors: amount = math.sin(amount * math.pi)
(I'm no Pygame expert - there may already be a built-in function for this.)
Set your foreground surface to the old color, over a background of the new one. Use set_alpha() to perform the fade. Once you're entirely on the new color, make that surface the foreground and make a new background of your third color. Repeat as desired.
This question and other references to "fade" and set_alpha() should allow you to finish the job.
Is that enough to get you moving?
I hesitated to post an answer because I came up with almost the same answer as Sloth's, but I'd just like to mention linear interpolation (short lerp, also called mix in OpenGL/GLSL). It's usually used to blend between two colors, but unfortunately pygame's Color class doesn't have a lerp method, so you have to define your own lerp function and use a list comprehension to interpolate the RGBA values.
Here's the lerp function from Wikipedia ported to Python (t is the weight and has to be between 0 and 1):
def lerp(v0, v1, t):
return (1 - t) * v0 + t * v1
Now you can lerp the RGBA values of two colors with a list comprehension.
color = [lerp(v0, v1, t) for v0, v1 in zip(color1, color2)]
E.g.:
>>> [lerp(v0, v1, .5) for v0, v1 in zip((0, 0, 0), (255, 255, 255))]
[127.5, 127.5, 127.5]
>>> [lerp(v0, v1, .25) for v0, v1 in zip((0, 0, 0), (255, 255, 255))]
[63.75, 63.75, 63.75]
If you don't need the alpha channel, you can also use pygame's Vector3 class which has a lerp method for your colors, then you'd just have to write: color = color1.lerp(color2, t).
import itertools
import pygame as pg
from pygame.math import Vector3
pg.init()
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
color_cycle = itertools.cycle([
Vector3(255, 0, 0),
Vector3(0, 255, 0),
Vector3(255, 255, 0),
Vector3(0, 0, 255),
])
color1 = next(color_cycle)
color2 = next(color_cycle)
color = color1
start_time = pg.time.get_ticks()
time_interval = 2000 # milliseconds
t = 0
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
now = pg.time.get_ticks()
t = (now - start_time) / time_interval
if t > 1:
t = 0
start_time = now
color1, color2 = color2, next(color_cycle)
color = color1.lerp(color2, t) # Lerp the two colors.
screen.fill(color)
pg.display.flip()
clock.tick(60)
I had a similar problem not to long ago, I went the crazy route of learning a bit of Calculus to do it
R = X, G = Y, B = Z
then wrote a program to calculate the difference between R0 and R1 (X0 and X1) etc.
#Nick Poling
#Fade Test V2
import random
#import mpmath
#import sympy
import time
import pygame
import shelve
import sys
from pygame.locals import *
#Always Initialize
pygame.init()
#sympy contains function line_3d?
#top level?
#formated string?
#Change Name Displayed in Corner
MY_FONT = 'freesansbold.ttf'
FONTSIZE_1 = 20
pygame.display.set_caption('Fade Test V2')
GAME_NAME = pygame.font.Font(MY_FONT, FONTSIZE_1)
#Boards
GAME_SCREEN_WIDTH = 900
GAME_SCREEN_HEIGHT = 600
Main_Game_Loop = 1
def get_close_out():
#Save_Game = get_Save_Game()
pygame.quit()
sys.exit()
def get_Save_Game():
#Save
global Main_Game_Loop
global GAME_SCREEN_COLOR
global GAME_SCREEN_WIDTH
global GAME_SCREEN_HEIGHT
saveGameShelfFile = shelve.open('Fade Test V1')
saveGameShelfFile['GAME_SCREEN_WIDTH'] = GAME_SCREEN_WIDTH
saveGameShelfFile['GAME_SCREEN_HEIGHT'] = GAME_SCREEN_HEIGHT
def get_Load_Game():
global Main_Game_Loop
global GAME_SCREEN_COLOR
global GAME_SCREEN_WIDTH
global GAME_SCREEN_HEIGHT
try:
#Load
saveGameShelfFile = shelve.open('Fade Test V1')
GAME_SCREEN_WIDTH = saveGameShelfFile['GAME_SCREEN_WIDTH']
GAME_SCREEN_HEIGHT = saveGameShelfFile['GAME_SCREEN_HEIGHT']
except:
#Save
#Save_Game = get_Save_Game()
#Load
saveGameShelfFile = shelve.open('Fade Test V1')
GAME_SCREEN_WIDTH = saveGameShelfFile['GAME_SCREEN_WIDTH']
GAME_SCREEN_HEIGHT = saveGameShelfFile['GAME_SCREEN_HEIGHT']
GAME_SCREEN = pygame.display.set_mode((GAME_SCREEN_WIDTH, GAME_SCREEN_HEIGHT),pygame.RESIZABLE)
#By putting the GAME_SCREEN here you can make the resize doable with the press of a button
#Does need to be un "#" to work when press "L"
def get_Colors():
#Colors
global BLACK
global WHITE
BLACK = [0, 0, 0]
WHITE = [255,255,255]
def get_Main_Game():
global Main_Game_Loop
global GAME_SCREEN_COLOR
global GAME_SCREEN_WIDTH
global GAME_SCREEN_HEIGHT
global BLACK
global WHITE
global Point_1
global Point_2
global Vector_1
global Vector_2
Colors = get_Colors()
GAME_SCREEN_COLOR = BLACK
#Load_Game = get_Load_Game()
GAME_SCREEN = pygame.display.set_mode((GAME_SCREEN_WIDTH, GAME_SCREEN_HEIGHT),pygame.RESIZABLE)
while Main_Game_Loop == 1:
GAME_SCREEN.fill(GAME_SCREEN_COLOR)
Equation_Of_Lines_in_3D_Space = get_Equation_Of_Lines_in_3D_Space()
for t in range(0,255):
XYZ_1 = [Point_1[0] + (Vector_1[0] * t), Point_1[1] + (Vector_1[1] * t), Point_1[2] + (Vector_1[2] * t)]
XYZ_2 = [Point_2[0] + (Vector_2[0] * t), Point_2[1] + (Vector_2[1] * t), Point_2[2] + (Vector_2[2] * t)]
GAME_SCREEN_COLOR = XYZ_1
GAME_SCREEN.fill(GAME_SCREEN_COLOR)
ticks = pygame.time.delay(5)
pygame.display.update()
for event in pygame.event.get():
if event.type == QUIT:
close_out = get_close_out()
elif event.type == pygame.VIDEORESIZE:
# There's some code to add back window content here.
surface = pygame.display.set_mode((event.w, event.h),pygame.RESIZABLE)
GAME_SCREEN_HEIGHT = event.h
GAME_SCREEN_WIDTH = event.w
pygame.display.update()
def get_Equation_Of_Lines_in_3D_Space():
global Point_1
global Point_2
global BLACK
global WHITE
global Vector_1
global Vector_2
global LCM_X1
global LCM_X2
global LCM_Y1
global LCM_Y2
global LCM_Z1
global LCM_Z2
Point_1 = BLACK
Point_2 = WHITE
Vector_1 = []
Vector_2 = []
LCM_X1 = []
LCM_X2 = []
LCM_Y1 = []
LCM_Y2 = []
LCM_Z1 = []
LCM_Z2 = []
for i in range(0,3):
#
Delta_XYZ_1 = Point_2[i] - Point_1[i]
Vector_1.append(Delta_XYZ_1)
Delta_XYZ_2 = Point_1[i] - Point_2[i]
Vector_2.append(Delta_XYZ_2)
factors = get_factors()
def get_factors():
global num_1
global num_2
global Vector_1
global Vector_2
global LCM_XYZ_1
global LCM_XYZ_2
for i in range(1,7):
if i == 1:
num_1 = Vector_1[0]
num_2 = 1
elif i == 2:
num_1 = Vector_2[0]
num_2 = 2
elif i == 3:
num_1 = Vector_1[1]
num_2 = 3
elif i == 4:
num_1 = Vector_2[1]
num_2 = 4
elif i == 5:
num_1 = Vector_1[2]
num_2 = 5
elif i == 6:
num_1 = Vector_2[2]
num_2 = 6
get_largest_and_lowest_common_factors(num_1)
get_LCM_XYZ()
Vector_1[0] = Vector_1[0] / LCM_XYZ_1[0]
Vector_1[1] = Vector_1[1] / LCM_XYZ_1[0]
Vector_1[2] = Vector_1[2] / LCM_XYZ_1[0]
#
Vector_2[0] = Vector_2[0] / LCM_XYZ_2[0]
Vector_2[1] = Vector_2[1] / LCM_XYZ_2[0]
Vector_2[2] = Vector_2[2] / LCM_XYZ_2[0]
def get_largest_and_lowest_common_factors(x):
global num_1
global num_2
global Vector_1
global Vector_2
global LCM_X1
global LCM_X2
global LCM_Y1
global LCM_Y2
global LCM_Z1
global LCM_Z2
#This function takes a number and puts its factor into a list
for i in range(1, x + 1) or range(-x, x - 1, -1):
try:
if x % i == 0:
if num_1 == Vector_1[0] and num_2 == 1:
LCM_X1.append(i)
elif num_1 == Vector_1[1] and num_2 == 3:
LCM_Y1.append(i)
elif num_1 == Vector_1[2] and num_2 == 5:
LCM_Z1.append(i)
elif num_1 == Vector_2[0] and num_2 == 2:
LCM_X2.append(i)
elif num_1 == Vector_2[1] and num_2 == 4:
LCM_Y2.append(i)
elif num_1 == Vector_2[2] and num_2 == 6:
LCM_Z2.append(i)
except ZeroDivisionError:
return 0
def get_LCM_XYZ():
global LCM_X1
global LCM_Y1
global LCM_Z1
global LCM_X2
global LCM_Y2
global LCM_Z2
global LCM_XYZ_1
global LCM_XYZ_2
#If 1 is 0
check_1 = 0
check_2 = 0
check_3 = 0
for i in range(0,3):
if i == 0:
if LCM_X1 == [] and LCM_X2 == []:
check_1 = 1
elif i == 1:
if LCM_Y1 == [] and LCM_Y2 == []:
check_2 = 2
elif i == 2:
if LCM_Z1 == [] and LCM_Z2 == []:
check_3 = 3
F_check = check_1 + check_2 + check_3
if F_check == 1:
LCM_X1.extend(LCM_Y1)
LCM_X2.extend(LCM_Y2)
elif F_check == 2:
LCM_Y1.extend(LCM_X1)
LCM_Y2.extend(LCM_X2)
elif F_check == 3:
if check_2 == 0:
LCM_Z1.extend(LCM_Y1)
LCM_Z2.extend(LCM_Y2)
elif check_2 != 0:
LCM_X1.extend(LCM_Z1)
LCM_X2.extend(LCM_Z2)
LCM_Y1.extend(LCM_Z1)
LCM_Y2.extend(LCM_Z2)
elif F_check == 4:
LCM_X1.extend(LCM_Y1)
LCM_X2.extend(LCM_Y2)
LCM_Z1.extend(LCM_Y1)
LCM_Z2.extend(LCM_Y2)
elif F_check == 5:
LCM_Y1.extend(LCM_X1)
LCM_Y2.extend(LCM_X2)
LCM_Z1.extend(LCM_X1)
LCM_Z2.extend(LCM_X2)
elif F_check == 6:
LCM_X1.append(1)
LCM_X2.append(1)
LCM_Y1.append(1)
LCM_Y2.append(1)
LCM_Z1.append(1)
LCM_Z2.append(1)
LCM_X1 = set(LCM_X1)
LCM_Y1 = set(LCM_Y1)
LCM_Z1 = set(LCM_Z1)
LCM_X2 = set(LCM_X2)
LCM_Y2 = set(LCM_Y2)
LCM_Z2 = set(LCM_Z2)
LCM_XYZ_1 = list(set.intersection(LCM_X1,LCM_Y1,LCM_Z1))
LCM_XYZ_2 = list(set.intersection(LCM_X2,LCM_Y2,LCM_Z2))
LCM_XYZ_1.sort(reverse = True)
LCM_XYZ_2.sort(reverse = True)
Main_Game = get_Main_Game()
Pygame provides the pygame.Color object. The object can construct a color from various arguments (e.g. RGBA color channels, hexadecimal numbers, strings, ...).
It also offers the handy method lerp, that can interpolate 2 colors:
Returns a Color which is a linear interpolation between self and the given Color in RGBA space
Use the pygame.Color object and the lerp method to interpolate a color form a list of colors:
def lerp_color(colors, value):
fract, index = math.modf(value)
color1 = pygame.Color(colors[int(index) % len(colors)])
color2 = pygame.Color(colors[int(index + 1) % len(colors)])
return color1.lerp(color2, fract)
The interpolation value must change over time. Use pygame.time.get_ticks to get the current time in milliseconds:
colors = ["green", "blue", "purple", "pink", "red", "orange", "yellow"]
value = (pygame.time.get_ticks() - start_time) / 1000
current_color = lerp_color(colors, value)
See also Color - Lerp
Minimal example:
import pygame, math
def lerp_color(colors, value):
fract, index = math.modf(value)
color1 = pygame.Color(colors[int(index) % len(colors)])
color2 = pygame.Color(colors[int(index + 1) % len(colors)])
return color1.lerp(color2, fract)
pygame.init()
window = pygame.display.set_mode((400, 300))
clock = pygame.time.Clock()
start_time = pygame.time.get_ticks()
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
start_time = pygame.time.get_ticks()
colors = ["green", "blue", "purple", "pink", "red", "orange", "yellow"]
value = (pygame.time.get_ticks() - start_time) / 1000
current_color = lerp_color(colors, value)
window.fill((255, 255, 255))
pygame.draw.circle(window, current_color, window.get_rect().center, 100)
pygame.display.flip()
pygame.quit()
exit()

When trying to blit text message onto pygame, function only runs once

I've written a simple RPG battle system. I want whatever is being printed to appear in a black text box on a pygame window. I've done that and written a function called TEXT(X) to display text on 3 different lines, but dispite me calling it after every print command it only runs once and displays only the first message.
If you run the program and compare it to the command prompt you'll know what I mean.
from pygame import *
from userInterface import Title, Dead
WIN_WIDTH = 640
WIN_HEIGHT = 400
HALF_WIDTH = int(WIN_WIDTH / 2)
HALF_HEIGHT = int(WIN_HEIGHT / 2)
DISPLAY = (WIN_WIDTH, WIN_HEIGHT)
DEPTH = 32
FLAGS = 0
init()
screen = display.set_mode(DISPLAY, FLAGS, DEPTH)
saveState = False
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRAY = (30, 30, 30)
FONT = font.SysFont("Courier New", 15)
heroHP = 1000
hero={'name' : 'Hero',
'height':4,
'lvl': 1,
'xp' : 0,
'reward' : 0,
'lvlNext':25,
'stats': {'str' : 12, # strength
'dex' : 4, # dexterity
'int' : 15, # intelligence
'hp' : heroHP, # health
'atk' : [250,350]}} # range of attack values
boss1={'name' : 'Imp',
'xp' : 0,
'lvlNext':25,
'reward' : 25,
'stats': {'hp' :400,
'atk' : [300,350]}}
ONE = None
TWO = None
THREE = None
def TEXT(X):
global ONE, TWO, THREE
if ONE == None:
ONE = X
elif ONE == X and TWO == None:
TWO = X
elif ONE and TWO and THREE == None:
THREE = X
elif ONE and TWO and THREE:
ONE = None
TWO = None
THREE = None
def level(char): # level up system
#nStr, nDex, nInt=0,0,0
while char['xp'] >= char['lvlNext']:
char['lvl']+=1
char['xp']=char['xp'] - char['lvlNext']
char['lvlNext'] = round(char['lvlNext']*1.5)
nStr=0.5*char['stats']['str']+1
nDex=0.5*char['stats']['dex']+1
nInt=0.5*char['stats']['int']+1
print(f'{char["name"]} levelled up to level {char["lvl"]}!') # current level
TEXT(f'{char["name"]} levelled up to level {char["lvl"]}!') # current level
print(f'( INT {round((char["stats"]["int"] + nInt))} - STR {round(char["stats"]["str"] + nStr)} - DEX {round(char["stats"]["dex"] + nDex)} )') # print new stats
TEXT(f'( INT {round((char["stats"]["int"] + nInt))} - STR {round(char["stats"]["str"] + nStr)} - DEX {round(char["stats"]["dex"] + nDex)} )') # print new statsm
char['stats']['str'] += nStr
char['stats']['dex'] += nDex
char['stats']['int'] += nInt
from random import randint
def takeDmg(attacker, defender): # damage alorithm
dmg = randint(attacker['stats']['atk'][0], attacker['stats']['atk'][1])
defender['stats']['hp'] = defender['stats']['hp'] - dmg
print(f'{defender["name"]} takes {dmg} damage!')
TEXT(f'{defender["name"]} takes {dmg} damage!')
if defender['stats']['hp'] <= 0:
print(f'{defender["name"]} has been slain...')
TEXT(f'{defender["name"]} has been slain...')
attacker['xp'] += defender['reward']
level(attacker)
if defender==hero:
#Dead()
input("Press ENTER to exit")
else:
hero['stats']['hp']=heroHP
#Title()
input("Press ENTER to exit")
def Battle(player, enemy):
global ONE, TWO, THREE
mouse.set_visible(1)
clock = time.Clock()
YES = Rect(100, 100, 50, 50)
NO = Rect(500, 100, 50, 50)
Text = Rect(70, 300, 500, 60)
#while ((enemy['stats']['hp']) > 0):
while True:
for e in event.get():
if e.type == QUIT:
exit("Quit") # if X is pressed, exit program
elif e.type == KEYDOWN:
if e.key == K_ESCAPE:
exit()
elif e.type == MOUSEBUTTONDOWN:
# 1 is the left mouse button, 2 is middle, 3 is right.
if e.button == 1:
# `event.pos` is the mouse position.
if YES.collidepoint(e.pos):
takeDmg(player, enemy)
print(f'{enemy["name"]} takes the opportunity to attack!')
TEXT(f'{enemy["name"]} takes the opportunity to attack!')
takeDmg(enemy, player)
elif NO.collidepoint(e.pos):
print(f'{enemy["name"]} takes the opportunity to attack!')
TEXT(f'{enemy["name"]} takes the opportunity to attack!')
takeDmg(enemy, player)
screen.fill(WHITE)
draw.rect(screen, BLACK, YES)
draw.rect(screen, BLACK, NO)
draw.rect(screen, GRAY, Text)
YES_surf = FONT.render(("YES"), True, WHITE)
NO_surf = FONT.render(("NO"), True, WHITE)
Text1_surf = FONT.render(ONE, True, WHITE)
Text2_surf = FONT.render(TWO, True, WHITE)
Text3_surf = FONT.render(THREE, True, WHITE)
screen.blit(YES_surf, YES)
screen.blit(NO_surf, NO)
screen.blit(Text1_surf, (80, 305))
screen.blit(Text2_surf, (80, 320))
screen.blit(Text3_surf, (80, 335))
display.update()
clock.tick(60)
Battle(hero, boss1)
A small change made it work for me:
def TEXT(X):
global ONE, TWO, THREE;
if ONE == None:
ONE = X
elif ONE and TWO == None: # "ONE == X" changed to "ONE"
TWO = X
elif ONE and TWO and THREE == None:
THREE = X
elif ONE and TWO and THREE:
ONE = None
TWO = None
THREE = None
I guess you can't compare strings with ==. You could probably compare them with somethin like "equals". I know that in Java == operator would compare addresses, that may not be the same when having two "equal" strings.
Edit: But even if that's true, the second call of "TEXT" would need to get the same parameter value to work with your code... You are comparing ONE to X.
TEXT("A");
TEXT("B");
wont work then.
I tested (your code) again with:
TEXT("A");
TEXT("A");
TEXT("C");
And it works.

Categories

Resources