initial commit

main
Tylan Tyson 1 year ago
commit 008741169e

2
.gitignore vendored

@ -0,0 +1,2 @@
.DS_STORE
venv/

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 428 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 503 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 511 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 679 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 638 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

@ -0,0 +1,168 @@
# Imports
import pygame
import pickle
from os import path
# Set Up
pygame.init()
fps = 60
clock = pygame.time.Clock()
tile_size = 48
cols = 35
margin = 100
screen_width = tile_size * cols
screen_height = 900 + margin
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('Level Editor')
clicked = False
level = 1
white = (255, 255, 255)
black = (0, 0, 0)
font = pygame.font.SysFont('Futura', 24)
#load images
background = pygame.image.load('images/background_editor.png')
left = pygame.image.load("images/left.png")
middle = pygame.image.load('images/middle.png')
right = pygame.image.load("images/right.png")
water = pygame.image.load('images/water1.png')
enemy = pygame.image.load('images/enemy.png')
door = pygame.image.load('images/door.png')
button_save = pygame.image.load('images/button_save.png')
button_load = pygame.image.load('images/button_load.png')
button_exit = pygame.image.load("images/button_exit.png")
# Create Empty World
world_data = []
for row in range(35):
r = [0] * 35
world_data.append(r)
# Output Text
def draw_text(text, font, text_col, x, y):
img = font.render(text, True, text_col)
screen.blit(img, (x, y))
# Grid
def draw_vertical():
for c in range(36):
# Vertical Lines
pygame.draw.line(screen, white, (c * tile_size, 0), (c * tile_size, screen_height - margin -36))
def draw_horizontal():
for c in range(19):
# Horizontal Lines
pygame.draw.line(screen, white, (0, c * tile_size), (screen_width, c * tile_size))
# Draw World
def draw_world():
for row in range(18):
for column in range(35):
if world_data[row][column] > 0:
# Left
if world_data[row][column] == 1:
image = pygame.transform.scale(left, (tile_size, tile_size))
screen.blit(image, (column * tile_size, row * tile_size))
# Middle
elif world_data[row][column] == 2:
image = pygame.transform.scale(middle, (tile_size, tile_size))
screen.blit(image, (column * tile_size, row * tile_size))
# Right
if world_data[row][column] == 3:
image = pygame.transform.scale(right, (tile_size, tile_size))
screen.blit(image, (column * tile_size, row * tile_size ))
# Water
elif world_data[row][column] == 4:
image = pygame.transform.scale(water, (tile_size, tile_size))
screen.blit(image, (column * tile_size, row * tile_size))
# Enemy
if world_data[row][column] == 5:
image = pygame.transform.scale(enemy, (tile_size, int(tile_size * 0.75)))
screen.blit(image, (column * tile_size, row * tile_size + (tile_size * 0.25)))
# Door
if world_data[row][column] == 6:
image = pygame.transform.scale(door, (tile_size, int(tile_size * 0.75)))
screen.blit(image, (column * tile_size, row * tile_size + (tile_size * 0.25)))
# Button Class
class Button():
# Init
def __init__(self, x, y, image):
self.image = image
self.images = pygame.transform.scale(image, (100,55))
self.rect = self.images.get_rect()
self.rect.topleft = (x, y)
self.clicked = False
# Draw
def draw(self):
self.clicked = False
pos = pygame.mouse.get_pos()
if self.rect.collidepoint(pos):
if pygame.mouse.get_pressed()[0] == 1 and self.clicked == False:
self.clicked = True
screen.blit(self.images, (self.rect.x, self.rect.y))
return self.clicked
# Scale and Initialise Classes
background = pygame.transform.scale(background, (1750,865))
load_button = Button(screen_width // 2 - 330, screen_height - 95, button_load)
save_button = Button(screen_width // 2 - 50, screen_height - 95, button_save)
exit_button = Button(screen_width // 2 + 250, screen_height - 95, button_exit)
# Game Loop
run = True
while run:
# Clock
clock.tick(fps)
# Background
screen.fill(black)
screen.blit(background, (0, 0))
# Grid
draw_vertical()
draw_horizontal()
draw_world()
#text showing current level
draw_text(f'Level: {level}', font, white, tile_size, screen_height - 80)
draw_text('Press W or S to change level', font, white, tile_size, screen_height - 60)
# Load Button
if load_button.draw():
#load in level data
if path.exists(f'levels/custom/level_{level}'):
pickle_in = open(f'levels/custom/level_{level}', 'rb')
world_data = pickle.load(pickle_in)
else:
pickle_out = open(f'levels/custom/level_{level}', 'wb')
pickle.dump(world_data, pickle_out)
pickle_out.close()
# Save Button
if save_button.draw():
pickle_out = open(f'levels/custom/level_{level}', 'wb')
pickle.dump(world_data, pickle_out)
pickle_out.close()
# Exit Button
if exit_button.draw():
run = False
# Event Handler
for event in pygame.event.get():
# Quit Game
if event.type == pygame.QUIT:
run = False
# Clicks To Chnage Tiles
if event.type == pygame.MOUSEBUTTONDOWN and clicked == False:
clicked = True
mouse_position = pygame.mouse.get_pos()
x = mouse_position[0] // tile_size
y = mouse_position[1] // tile_size
# Check That The Coordinates Are Within The Tile Area
if x < 35 and y < 18:
# Update Tile Value
if pygame.mouse.get_pressed()[0] == 1:
world_data[y][x] += 1
if world_data[y][x] > 6:
world_data[y][x] = 0
elif pygame.mouse.get_pressed()[2] == 1:
world_data[y][x] -= 1
if world_data[y][x] < 0:
world_data[y][x] = 6
if event.type == pygame.MOUSEBUTTONUP:
clicked = False
# Change Level
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
level += 1
elif event.key == pygame.K_s and level > 1:
level -= 1
#update game display window
pygame.display.update()
# Quit Pygame
pygame.quit()

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -0,0 +1,448 @@
# Imports
import pygame
import pygame.locals
import pygame_textbox
import os
from os import path
from threading import Thread
import pickle
import time
import random
# Set Up
pygame.init()
tile_size = 50
screen_width = tile_size * 35
screen_height = (900)
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Unexpected Adventure")
fps = 60
clock = pygame.time.Clock()
level = 1
main_menu = True
game_over = False
white = (255, 255, 255)
font = pygame.font.SysFont('Futura', 24)
doesnt_exist = False
scroll = [0,0]
# Load Images
background1 = pygame.image.load("images/background4.png").convert_alpha()
background2 = pygame.image.load("images/background3.png").convert_alpha()
background3 = pygame.image.load("images/background2.png").convert_alpha()
background4 = pygame.image.load("images/background1.png").convert_alpha()
left = pygame.image.load("images/left.png").convert_alpha()
middle = pygame.image.load("images/middle.png").convert()
right = pygame.image.load("images/right.png").convert_alpha()
door = pygame.image.load("images/door.png").convert_alpha()
button_edit = pygame.image.load("images/button_edit.png").convert()
button_custom = pygame.image.load("images/button_custom.png").convert()
button_start = pygame.image.load("images/button_start.png").convert()
button_exit = pygame.image.load("images/button_exit.png").convert()
button_music = pygame.image.load("images/button_music.png").convert()
button_restart = pygame.image.load("images/button_restart.png").convert()
# Sprite Groups
water_group = pygame.sprite.Group()
enemy_group = pygame.sprite.Group()
door_group = pygame.sprite.Group()
# World Class
class World():
# Init
def __init__(self, data):
self.tile_list = []
row_count = 0
for row in data:
column_count = 0
for tile in row:
if tile == 1:
tile = pygame.transform.scale(left, (tile_size, tile_size))
tile_rect = tile.get_rect()
tile_rect.x = column_count * tile_size
tile_rect.y = row_count * tile_size
tile = (tile, tile_rect)
self.tile_list.append(tile)
elif tile == 2:
tile = pygame.transform.scale(middle, (tile_size, tile_size))
tile_rect = tile.get_rect()
tile_rect.x = column_count * tile_size
tile_rect.y = row_count * tile_size
tile = (tile, tile_rect)
self.tile_list.append(tile)
elif tile == 3:
tile = pygame.transform.scale(right, (tile_size, tile_size))
tile_rect = tile.get_rect()
tile_rect.x = column_count * tile_size
tile_rect.y = row_count * tile_size
tile = (tile, tile_rect)
self.tile_list.append(tile)
elif tile == 4:
water = Water(column_count * tile_size, row_count * tile_size + (tile_size // 2))
water_group.add(water)
elif tile == 5:
enemy = Enemy(column_count * tile_size, row_count * tile_size + 15, row_count, column_count, data)
enemy_group.add(enemy)
elif tile == 6:
door = Door(column_count * tile_size, row_count * tile_size - (tile_size // 2))
door_group.add(door)
column_count += 1
row_count +=1
# Draw World
def draw(self):
for tile in self.tile_list:
screen.blit(tile[0], (tile[1].x - scroll[0] + screen_width // 2, tile[1].y - scroll[1] + screen_height // 2))
# Water
class Water(pygame.sprite.Sprite):
# Init
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
image = pygame.image.load("images/water1.png").convert_alpha()
self.image = pygame.transform.scale(image, (tile_size, tile_size))
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y -25
self.images = []
self.image_index = 1
for number in range(1, 17):
img = pygame.image.load(f"images/water{number}.png").convert_alpha()
img = pygame.transform.scale(img, (tile_size, tile_size))
self.images.append(img)
self.image = self.images[self.image_index]
self.counter = 0
# Update
def update(self):
self.image_index += 1
if self.image_index < len(self.images):
self.image = self.images[self.image_index]
else:
self.image_index = 0
self.image = self.images[self.image_index]
def render(self, screen):
screen.blit(self.image, (self.rect.x - scroll[0] + screen_width // 2, self.rect.y - scroll[1] + screen_height // 2))
# Enemy Class
class Enemy(pygame.sprite.Sprite):
# Init
def __init__(self, x, y, row_count, column_count, data):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("images/enemy.png").convert_alpha()
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.move_direction = 5
self.move_counter = 0
self.row_count = row_count
self.column_count = column_count
self.data = data
# Update
def update(self):
if self.data[self.row_count + 1][self.column_count] == 2:
self.rect.x += self.move_direction
self.move_counter += 1
if self.move_counter > 10:
self.move_direction *= - 1
self.move_counter*= -1
def render(self, screen):
screen.blit(self.image, (self.rect.x - scroll[0] + screen_width // 2, self.rect.y - scroll[1] + screen_height // 2))
# Door
class Door(pygame.sprite.Sprite):
# Init
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
image = pygame.image.load("images/door.png").convert_alpha()
self.image = pygame.transform.scale(image, (tile_size, tile_size + 26))
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def render(self, screen):
screen.blit(self.image, (self.rect.x - scroll[0] + screen_width // 2, self.rect.y - scroll[1] + screen_height // 2))
# Button Class
class Button():
# Init
def __init__(self, x, y, image):
self.image = image
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
# Draw Button
def draw(self):
mouse_position = pygame.mouse.get_pos()
clicked = False
if self.rect.collidepoint(mouse_position):
if pygame.mouse.get_pressed()[0] == 1:
clicked = True
time.sleep(0.2)
screen.blit(self.image, self.rect)
return clicked
# Player Class
class Player():
# Init
def __init__(self, x, y):
self.reset(x, y)
self.game_over = False
self.image_index = 0
# Move Player
def update(self, game_over , main_menu):
# Frame Rate
clock.tick(fps)
# Move Player
dx = 0
dy = 0
if game_over == False:
key = pygame.key.get_pressed()
# Jump
if key[pygame.K_w] and self.jumped == False and self.in_air == False:
self.vel_y = -15
self.jumped = True
elif key[pygame.K_w] == False:
self.jumped = False
# Left
if key[pygame.K_a]:
dx -= 7
self.direction = "left"
# Right
elif key[pygame.K_d]:
dx += 7
self.direction = "right"
# Animations
if key[pygame.K_a] == False and key[pygame.K_d] == False:
if self.direction == "left":
self.image = self.images_left[0]
elif self.direction == "right":
self.image = self.images_right[0]
else:
self.index += 1
if self.index >= len(self.images_right) or self.index >= len(self.images_left):
self.index = 0
if self.direction == "left":
self.image = self.images_left[self.index]
elif self.direction == "right":
self.image = self.images_right[self.index]
# Gravity
self.vel_y += 1
if self.vel_y > 10:
self.vel_y = 15
dy += self.vel_y
# Collisions
self.in_air = True
for tile in world.tile_list:
# Animations
if tile[1].colliderect(self.rect.x + dx, self.rect.y, self.width, self.height):
if dx < 0:
self.image = self.images_left[0]
else:
self.image = self.images_right[0]
# X and Y
if tile[1].colliderect(self.rect.x + dx, self.rect.y, self.width, self.height):
dx = 0
# Vertical
if tile[1].colliderect(self.rect.x, self.rect.y + dy, self.width, self.height):
if self.vel_y >= 0:
dy = tile[1].top - self.rect.bottom
self.in_air = False
elif self.vel_y < 0:
dy = tile[1].bottom - self.rect.top
self.vel_y = 0
# Collision With Door
if pygame.sprite.spritecollide(self, door_group, False):
main_menu = True
# Game Over Conditions
if self.rect.bottom > screen_height:
game_over = True
elif pygame.sprite.spritecollide(self, water_group, False):
game_over = True
elif pygame.sprite.spritecollide(self, enemy_group, False):
game_over = True
# Game Over
if game_over == True:
self.image = self.dead_image
self.rect.y -= 5
# Update Coordinates
self.rect.x += dx
self.rect.y += dy
# Draw Player
screen.blit(self.image, (self.rect.x - scroll[0] + screen_width // 2, self.rect.y - scroll[1] + screen_height // 2))
return game_over, main_menu
# Reset Player
def reset(self, x, y):
# Set Up
self.images_right = []
self.images_left = []
self.index = 0
# Load Images
for num in range(1, 5):
img_right = pygame.image.load(f"images/guy{num}.png").convert_alpha()
img_right = pygame.transform.scale(img_right, (40, 80))
img_left = pygame.transform.flip(img_right, True, False)
self.images_right.append(img_right)
self.images_left.append(img_left)
self.dead_image = pygame.image.load("images/ghost.png").convert_alpha()
self.image = self.images_right[0]
# Rect
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.width = self.image.get_width()
self.height = self.image.get_height()
# Other Variables
self.direction = 0
self.vel_y = 0
self.jumped = False
self.in_air = True
# Level Editor
def level_editor():
print(os.path.join(os.getcwd(), "venv", "bin", "python3.9"))
os.system(os.path.join(os.getcwd(), "venv", "bin", "python3.9") + " " + os.path.join(os.getcwd(), "level_editor.py"))
# Draw Text
def draw_text(text, font, text_col, x, y):
img = font.render(text, True, text_col)
screen.blit(img, (x, y))
# Scale and Initialise Classes
background1 = pygame.transform.scale(background1, (2000, 1000))
background2 = pygame.transform.scale(background2, (2000, 1000))
background3 = pygame.transform.scale(background3, (2000, 1000))
background4 = pygame.transform.scale(background4, (2000, 1000))
start_button = pygame.transform.scale(button_start, (200, 100))
exit_button = pygame.transform.scale(button_exit, (80, 35))
player = Player(100, screen_height - 180)
start_button = Button(screen_width // 2 -100 , screen_height // 2 - 100, start_button)
exit_button = Button(screen_width // 2 - 40, screen_height // 2 + 50, exit_button)
edit_button = Button(screen_width // 2 -250, screen_height // 2 + 30, button_edit)
custom_button = Button(screen_width // 2 + 150 , screen_height // 2 + 30 , button_custom)
music_button = Button(screen_width // 2 + 700 , screen_height // 2 - 400 , button_music)
menu_button = Button(screen_width //2 + 700 , screen_height //2 - 300, button_exit)
restart_button = Button(screen_width // 2 - 50, screen_height // 2 , button_restart)
# Background Music
pygame.mixer.music.load("sounds/music.mp3")
pygame.mixer.music.play(-1)
paused = False
# Game Loop
run = True
while run:
# FPS
clock.tick(fps)
screen.fill((0,0,0))
# QUIT
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT:
run = False
# Draw Background
screen.blit(background4, (0 - scroll[0]* 0.2, 0))
screen.blit(background3, (0 - scroll[0]* 0.4, 0))
screen.blit(background2, (0 - scroll[0]* 0.5, 0))
screen.blit(background1, (0 - scroll[0]* 0.6, 0))
screen.blit(background4, (2000 - scroll[0]* 0.2, 0))
screen.blit(background3, (2000 - scroll[0]* 0.4, 0))
screen.blit(background2, (2000 - scroll[0]* 0.5, 0))
screen.blit(background1, (2000 - scroll[0]* 0.6, 0))
screen.blit(background4, (-2000 - scroll[0]* 0.2, 0))
screen.blit(background3, (-2000 - scroll[0]* 0.4, 0))
screen.blit(background2, (-2000 - scroll[0]* 0.5, 0))
screen.blit(background1, (-2000 - scroll[0]* 0.6, 0))
# Menu
if main_menu:
game_over = False
# Start
if start_button.draw():
enemy_group.empty()
water_group.empty()
door_group.empty()
if path.exists(f"levels/storymode/level_{level}"):
pickle_in = open(f"levels/storymode/level_{level}", "rb")
level_data = pickle.load(pickle_in)
world = World(level_data)
main_menu = False
player.reset(100, screen_height - 130)
doesnt_exist = False
# Level Editor
elif edit_button.draw() == True:
thread = Thread(target = level_editor)
thread.start()
doesnt_exist = False
# Custom Maps
if custom_button.draw():
enemy_group.empty()
water_group.empty()
door_group.empty()
selected_level = pygame_textbox.textinput()
if path.exists(f"levels/custom/level_{selected_level}"):
pickle_in = open(f"levels/custom/level_{selected_level}", "rb")
level_data = pickle.load(pickle_in)
world = World(level_data)
main_menu = False
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Unexpected Adventure")
player.reset(100, screen_height - 130)
doesnt_exist = False
else:
doesnt_exist = True
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Unexpected Adventure")
player.reset(100, screen_height - 130)
if doesnt_exist:
draw_text("Level Doesn't Exist", font, white, screen_width // 2 - 75, screen_height // 2 + 17)
# Exit
if exit_button.draw():
run = False
# Music
if music_button.draw():
if paused == False:
pygame.mixer.music.pause()
paused = True
else:
pygame.mixer.music.unpause()
paused = False
# Game
if main_menu == False:
# Draw World
world.draw()
water_group.update()
for water in water_group:
water.render(screen)
enemy_group.update()
for enemy in enemy_group:
enemy.render(screen)
door_group.update()
for door in door_group:
door.render(screen)
# Update Player
game_over, main_menu = player.update(game_over , main_menu)
scroll[0] += (player.rect.x - scroll[0])*0.02
scroll[1] = 450
# Music Button
if music_button.draw():
if paused == False:
pygame.mixer.music.pause()
paused = True
else:
pygame.mixer.music.unpause()
paused = False
# Menu Button
if menu_button.draw():
player.reset(100, screen_height - 130)
enemy_group.empty()
water_group.empty()
door_group.empty()
main_menu = True
game_over = False
# Restart Button
if game_over == True:
if restart_button.draw():
player.reset(100, screen_height - 130)
game_over = False
# Update Display
pygame.display.update()
# Quit Pygame
pygame.quit()

@ -0,0 +1,32 @@
# Imports
import pygame_textinput
import pygame
# Set Up
pygame.init()
# Class
def textinput():
# Window
screen = pygame.display.set_mode((300, 50))
pygame.display.set_caption("Enter level number")
# Set Up
textinput = pygame_textinput.TextInput()
clock = pygame.time.Clock()
# Game Loop
run = True
while run:
# Background
screen.fill((225, 225, 225))
events = pygame.event.get()
# QUIT
for event in events:
if event.type == pygame.QUIT:
exit()
# Feed Events
if textinput.update(events):
run = False
return textinput.get_text()
# Output
screen.blit(textinput.get_surface(), (10, 10))
# Display
pygame.display.update()
clock.tick(30)

@ -0,0 +1,128 @@
import os.path
import pygame
import pygame.locals as pl
pygame.font.init()
class TextInput:
def __init__(
self,
initial_string="",
font_family="",
font_size=35,
antialias=True,
text_color=(0, 0, 0),
cursor_color=(0, 0, 1),
repeat_keys_initial_ms=400,
repeat_keys_interval_ms=35,
max_string_length=-1,
password=False):
self.antialias = antialias
self.text_color = text_color
self.font_size = font_size
self.max_string_length = max_string_length
self.password = password
self.input_string = initial_string
if not os.path.isfile(font_family):
font_family = pygame.font.match_font(font_family)
self.font_object = pygame.font.Font(font_family, font_size)
self.surface = pygame.Surface((1, 1))
self.surface.set_alpha(0)
self.keyrepeat_counters = {}
self.keyrepeat_intial_interval_ms = repeat_keys_initial_ms
self.keyrepeat_interval_ms = repeat_keys_interval_ms
self.cursor_surface = pygame.Surface((int(self.font_size / 20 + 1), self.font_size))
self.cursor_surface.fill(cursor_color)
self.cursor_position = len(initial_string)
self.cursor_visible = True
self.cursor_switch_ms = 500
self.cursor_ms_counter = 0
self.clock = pygame.time.Clock()
def update(self, events):
for event in events:
if event.type == pygame.KEYDOWN:
self.cursor_visible = True
if event.key not in self.keyrepeat_counters:
if not event.key == pl.K_RETURN:
self.keyrepeat_counters[event.key] = [0, event.unicode]
if event.key == pl.K_BACKSPACE:
self.input_string = (
self.input_string[:max(self.cursor_position - 1, 0)]
+ self.input_string[self.cursor_position:]
)
self.cursor_position = max(self.cursor_position - 1, 0)
elif event.key == pl.K_DELETE:
self.input_string = (
self.input_string[:self.cursor_position]
+ self.input_string[self.cursor_position + 1:]
)
elif event.key == pl.K_RETURN:
return True
elif event.key == pl.K_RIGHT:
self.cursor_position = min(self.cursor_position + 1, len(self.input_string))
elif event.key == pl.K_LEFT:
self.cursor_position = max(self.cursor_position - 1, 0)
elif event.key == pl.K_END:
self.cursor_position = len(self.input_string)
elif event.key == pl.K_HOME:
self.cursor_position = 0
elif len(self.input_string) < self.max_string_length or self.max_string_length == -1:
self.input_string = (
self.input_string[:self.cursor_position]
+ event.unicode
+ self.input_string[self.cursor_position:]
)
self.cursor_position += len(event.unicode)
elif event.type == pl.KEYUP:
if event.key in self.keyrepeat_counters:
del self.keyrepeat_counters[event.key]
for key in self.keyrepeat_counters:
self.keyrepeat_counters[key][0] += self.clock.get_time()
if self.keyrepeat_counters[key][0] >= self.keyrepeat_intial_interval_ms:
self.keyrepeat_counters[key][0] = (
self.keyrepeat_intial_interval_ms
- self.keyrepeat_interval_ms
)
event_key, event_unicode = key, self.keyrepeat_counters[key][1]
pygame.event.post(pygame.event.Event(pl.KEYDOWN, key=event_key, unicode=event_unicode))
string = self.input_string
if self.password:
string = "*" * len(self.input_string)
self.surface = self.font_object.render(string, self.antialias, self.text_color)
self.cursor_ms_counter += self.clock.get_time()
if self.cursor_ms_counter >= self.cursor_switch_ms:
self.cursor_ms_counter %= self.cursor_switch_ms
self.cursor_visible = not self.cursor_visible
if self.cursor_visible:
cursor_y_pos = self.font_object.size(self.input_string[:self.cursor_position])[0]
if self.cursor_position > 0:
cursor_y_pos -= self.cursor_surface.get_width()
self.surface.blit(self.cursor_surface, (cursor_y_pos, 0))
self.clock.tick()
return False
def get_surface(self):
return self.surface
def get_text(self):
return self.input_string
def get_cursor_position(self):
return self.cursor_position
def set_text_color(self, color):
self.text_color = color
def set_cursor_color(self, color):
self.cursor_surface.fill(color)
def clear_text(self):
self.input_string = ""
self.cursor_position = 0
if __name__ == "__main__":
pygame.init()
textinput = TextInput()
screen = pygame.display.set_mode((1000, 200))
clock = pygame.time.Clock()
while True:
screen.fill((225, 225, 225))
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT:
exit()
textinput.update(events)
screen.blit(textinput.get_surface(), (10, 10))
pygame.display.update()
clock.tick(30)

@ -0,0 +1 @@
pygame==2.3.0

Binary file not shown.
Loading…
Cancel
Save