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.
Related
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
I'm fairly new to coding (like 3 weeks in) and I've been trying to make a turn-based RPG battle system using pygame. I've encountered a problem involving pygame's key.get_pressed. I'm making a dropdown menu thing where if you press ENTER, a smaller black box should appear and when you press ENTER again, the box should disappear. Unfortunately, the black box appears but disappears almost immediately. I used the print function as a debug to find the error and it seems that the program registers the second ENTER press (the one that should close the box) without it ever being pressed. Any help would be greatly appreciated. I am also using windows 10 and python 3.6
import pygame
pygame.init()
win = pygame.display.set_mode((820,567))
pygame.display.set_caption('Basic battle')
drop_menu_attack = pygame.image.load('drop menu attack.png')
health_pp = pygame.image.load('hp and pp.png')
menu_img = pygame.image.load('menu.png')
attack_img = pygame.image.load('attack.png')
defend_img = pygame.image.load('defend.png')
bag_img = pygame.image.load('bag.png')
background_img = pygame.image.load('rpg background.gif')
Snake_enemy_img = pygame.image.load('pixil-frame-0.png')
clock = pygame.time.Clock()
class player(object):
def __init__ (self, x, y, width, height):
self.x = x
self.y = y
self.width = width
self.height = height
self.cursor_state = 1
self.attack_x = 100
self.defend_x = 325
self.bag_x = 575
self.top_menu_y = 70
class drop_menu(object):
def __init__ (self, x, y):
self.x = x
self.y = y
self.drop_menu_state = False
def cursor_position():
if c_p.cursor_state == 1:
print ('it should be on attack')
c_p.x = c_p.attack_x
c_p.y = c_p.top_menu_y
elif c_p.cursor_state == 2:
print ('it hould be on defend')
c_p.x = c_p.defend_x
c_p.y = c_p.top_menu_y
elif c_p.cursor_state == 3:
print ('it should be on bag')
c_p.x = c_p.bag_x
c_p.y = c_p.top_menu_y
elif c_p.cursor_state > 3:
c_p.cursor_state = 3
print ('it should be on bag')
c_p.x = c_p.bag_x
c_p.y = c_p.top_menu_y
elif c_p.cursor_state < 1:
c_p.cursor_state = 1
print ('it should be on attack')
c_p.x = c_p.attack_x
c_p.y = c_p.top_menu_y
def select():
if c_p.cursor_state == 1:
d_m.drop_menu_state = True
print (d_m.y)
while d_m.drop_menu_state:
pygame.time.delay(150)
win.blit (drop_menu_attack, (d_m.x, d_m.y))
pygame.display.update()
print ('dooooog')
keys = pygame.key.get_pressed()
if d_m.drop_menu_state == True:
if keys[pygame.K_RETURN]:
d_m.drop_menu_state = False
print('SSSSSS')
pygame.event.pump()
def redraw_gamewindow():
win.blit (background_img, (0,0))
win.blit (Snake_enemy_img, (300, 174))
win.blit (menu_img, (25, 425 ))
win.blit (menu_img, (25, 10))
win.blit (health_pp, (70, 450))
win.blit (attack_img, (c_p.attack_x + 30, c_p.top_menu_y - 15))
win.blit (defend_img, (c_p.defend_x + 30, c_p.top_menu_y - 15))
win.blit (bag_img, (c_p.bag_x + 30, c_p.top_menu_y - 15))
pygame.draw.rect(win, (255, 255, 255), (c_p.x, c_p.y, 7 , 7))
pygame.display.update()
d_m = drop_menu(25, 125)
print (d_m.x)
c_p = player(100, 70, 7,7)
run = True
while run:
clock.tick(27)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
if keys[pygame.K_RIGHT]:
c_p.cursor_state = c_p.cursor_state + 1
cursor_position()
pygame.time.delay(150)
if keys[pygame.K_LEFT]:
c_p.cursor_state = c_p.cursor_state -1
cursor_position()
pygame.time.delay(150)
if keys[pygame.K_RETURN]:
select()
pygame.time.delay(500)
redraw_gamewindow()
So what's happening is that you're holding the ENTER button. In the while loop, when you press enter, it calls the select() function, which then detects the ENTER that is still being pressed. Let me draw a visual-ish:
ENTER is pressed -> select() is called, drop_menu_state turns True -> select() detects ENTER still being pressed -> drop_menu_state turns false
You may be asking, how does it detect? Well the frames are running at a wanted 27 frames per second. So it will change the state of drop menu state every 1/27 of a second while the ENTER key is being pressed. If you are able to press and release the ENTER key for less than 1/27 of a second, it will work properly.
There are 3 solutions. Either bind the closing of the menu to another key, add a short timer, or use an event loop. My style of programming would be to add a timer.
import time
pre_time = time.time()
def select():
... # code in select()
if d_m.drop_menu_state and pre_time + 5 > time.time() and keys[pygame.K_RETURN]:
pre_time = time.time()
d_m.drop_menu_state = False
I simplified your code a bit (no == True) What the pre_time + 5 > time.time() is saying is has it been five seconds since the last time pre_time has been defined as the current time.
I hope this helps!
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.
I found this input box module on the internet but it only allows lower case no upper. So could someone tell me what to change in the module to allow caps as im creating a small multiplayer game and i need login system and chatbox.
Here is the code example I am working with
# by Timothy Downs, inputbox written for my map editor
# This program needs a little cleaning up
# It ignores the shift key
# And, for reasons of my own, this program converts "-" to "_"
# A program to get user input, allowing backspace etc
# shown in a box in the middle of the screen
# Called by:
# import inputbox
# answer = inputbox.ask(screen, "Your name")
#
# Only near the center of the screen is blitted to
import pygame, pygame.font, pygame.event, pygame.draw, string
from pygame.locals import *
def get_key():
while 1:
event = pygame.event.poll()
if event.type == KEYDOWN:
return event.key
else:
pass
def display_box(screen, message):
"Print a message in a box in the middle of the screen"
fontobject = pygame.font.Font(None,18)
pygame.draw.rect(screen, (0,0,0),
((screen.get_width() / 2) - 100,
(screen.get_height() / 2) - 10,
200,20), 0)
pygame.draw.rect(screen, (255,255,255),
((screen.get_width() / 2) - 102,
(screen.get_height() / 2) - 12,
204,24), 1)
if len(message) != 0:
screen.blit(fontobject.render(message, 1, (255,255,255)),
((screen.get_width() / 2) - 100, (screen.get_height() / 2) - 10))
pygame.display.flip()
def ask(screen, question):
"ask(screen, question) -> answer"
pygame.font.init()
current_string = []
display_box(screen, question + ": " + string.join(current_string,""))
while 1:
inkey = get_key()
if inkey == K_BACKSPACE:
current_string = current_string[0:-1]
elif inkey == K_RETURN:
break
elif inkey == K_MINUS:
current_string.append("_")
elif inkey <= 127:
current_string.append(chr(inkey))
display_box(screen, question + ": " + string.join(current_string,""))
return string.join(current_string,"")
def main():
screen = pygame.display.set_mode((320,240))
print ask(screen, "Name") + " was entered"
if __name__ == '__main__': main()
Thx!
If you change the corresponding code to:
elif inkey <= 127:
if pygame.key.get_mods() & KMOD_SHIFT or pygame.key.get_mods() & KMOD_CAPS: # if shift is pressed or caps is on
current_string.append(chr(inkey).upper()) # make string uppercase
else:
current_string.append(chr(inkey)) # else input is lower
That should work.
If you want more info on keyboard modifier states look here
import pygame
from pygame.locals import *
import random
import time
pygame.init()
randomNumber = random.randint(1,600)
randomNumber2 = random.randint(1,600)
x = 0
text = ""
squareCount = 0
beenHere = 0
# colours = (red, green, blue)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
WHITE = (255, 255, 255)
LBLUE = (0, 123, 255)
colour = RED
# Make a window appear
size = (700, 500)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Square Chase | Score: 0")
screen.fill(LBLUE)
pygame.display.flip()
pygame.time.set_timer(USEREVENT + 1, 1500)
done = False
clock = pygame.time.Clock()
while done == False:
for event in pygame.event.get():
print(event)
if event.type == pygame.QUIT:
done = True
if event.type == USEREVENT + 1:
screen.fill(LBLUE)
randomNumber = random.randint(1,625)
randomNumber2 = random.randint(1,420)
mySquare = pygame.draw.rect(screen,colour,(randomNumber,randomNumber2,50,50),5)
squareCount = squareCount + 1
if squareCount == 50:
done == true
pygame.display.flip()
if event.type == pygame.MOUSEBUTTONDOWN:
y, z = pygame.mouse.get_pos()
is_inside = mySquare.collidepoint(y, z)
if is_inside and colour == GREEN:
x = x+1
text = str(x)
pygame.display.set_caption("Square Chase | Score " + text)
colour = RED
elif is_inside:
x = x+1
text = str(x)
pygame.display.set_caption("Square Chase | Score " + text)
colour = GREEN
clock.tick(20)
pygame.quit()
I am aiming to create a game in which the user has to click on a square for their score to increase. They get 50 chances to do this. If they click in the square within the 1.5 seconds the colour of the square changes.
The above code works apart from each time a new square is drawn the user could click on it say 5 times and their score will go up by 5. Any suggestions as to how to get the score to increase by just one? Thanks in advance.
Wish I could just use a comment but I have lack of reputation.
I didn't look through all your code, but your description makes it sound like a simple flag would be able to help you.
Once you recognize it has been clicked, increment the score AND set a boolean.
So in essence you will want something along the lines of
if clicked == false
score = score+1
clicked = true
You will want to clear the flag back to false once another block has appeared.
Wouldn't it be better, if a new square would show up after a successful keypress? That way the game would be more dynamic.
It's easy to change this. Instead of using user events that are called every 1.5 sec, sum the value returned by clock.tick() and when their sum will be greater than 1500 ms, create a new rectangle. This is a better approach, because you can call the method that creates a new square and reset the timer right after a successful keypress.
Some code to get you started:
def new_rect(screen,colour):
screen.fill(LBLUE)
randomNumber = random.randint(1,625)
randomNumber2 = random.randint(1,420)
mySquare = pygame.draw.rect(screen,colour,(randomNumber,randomNumber2,50,50),5)
return mySquare
done = False
clock = pygame.time.Clock()
timer_var = 0
while done == False:
if(timer_var > 1500):
timer_var = 0
mySquare = new_rect(screen,color)
squareCount = squareCount + 1
if squareCount == 50:
done == true
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
y, z = pygame.mouse.get_pos()
is_inside = mySquare.collidepoint(y, z)
if is_inside:
x = x+1
text = str(x)
pygame.display.set_caption("Square Chase | Score " + text)
timer_var = 0
new_rect(screen,colour)
squareCount = squareCount + 1
if squareCount == 50:
done == true
if colour == GREEN:
colour = RED
else:
colour = GREEN
timer_var += clock.tick(20)
pygame.quit()