声明一下先:
(0):其实没有那么高大上,只是突发奇想,便分享出来,不喜勿喷。
(1):只适合“不想花费太大学习成本来制作属于自己的Galgame”的宝宝体质。
(2):仅适合“简单、朴素的Galgame”的制作与合成。
(3):本文来带大家一起手把手实现一下,仅仅讲,代码拿走用不了; 之后会发使用版本的。
朴实无华的小特点:
①、Gal♥Py是使用“Python”制作的、基于“Excel-csv”操作的2D-Galgame引擎。PS:(如果有3D图片 ,也不是不行)
②、与流行的“Renpy”等引擎不同的关键是:
Gal♥Py 平时的操作无需任何代码 ,只有在“定义自己游戏的玩法时”才会牵扯到代码的设计 ;当然,缺点就是“个人定制”选项的操作过少(太粗糙)。
③、对于平时的操作,只需要在你的项目对应的 csv 文件里进行“思想的构建”即可 ,简言之“在每个镜头对应的表格上添加需要在此镜头里出现的人物、背景、音乐等等的名字”而已。
Gal♥Py的思路:
1):需要一个“数据库”,以此实现Excel-csv数据的“增删改”各种操作。
2):需要写一个pygame屏幕,来实现游戏逻辑。
3):需要写一个tkinter屏幕,来进行对“游戏项目”的“读删改”。
4):以上三点启示很好实现,关键是其三者的交互。
实现一下来:
Ⅰ、所谓的“数据库”:(不是关键的函数可以不看)
(1)需要的库 (可能有些模块没用到,没事的不影响)
# -*- coding: utf-8 -*-
from csv import DictReader ,DictWriter
from glob import iglob
from re import findall as re_findall
from collections import deque
from typing import NoReturn ,Self
关键的库:
csv:
DictReader -> 读取csv
DictWriter -> 写入csv
(2)“数据库”类 (可能出现了很多没见过的东西,没事那些不影响)
class CsvDataBase(object):
def __new__(cls) -> Type.Addr:
cls.abspath:str = '/'.join([each for index ,each in enumerate(__file__.split('\\')[:-1])])+'/'
cls.memory:list = deque([])
return super(CsvDataBase ,cls).__new__(cls)
def __init__(self) -> NoReturn:
pass
@staticmethod
def get_coding(target:str) -> str:
return "utf-8" if target[target.index('.')+1:] in {"txt" ,"dat"} else "utf-8-sig"
def write(self ,target:Type.Path ,* ,data:list[dict] ,mode='w') -> NoReturn:
CsvDataBase.memory.append(target)
with open(target ,mode ,encoding=CsvDataBase.get_coding(target) ,newline='') as file:
writer = DictWriter(file ,fieldnames=list(data[0]))
writer.writeheader()
writer.writerows(data)
stdout.write("Save OK!\n")
def read(self ,target:Type.Path ,* ,mode='r') -> dict:
with open(target ,mode ,encoding=CsvDataBase.get_coding(target) ,newline='') as file:
reader = DictReader(file)
return [each for index ,each in enumerate(reader)]
def seek(self ,path:str ,name:str) -> str|None:
for index ,each in enumerate(iglob(path+"//*")):
if re_findall(r".*?{}.*?".format(name) ,each)
return each
return None
关键的函数:
*write ->
结合DictWriter,写入csv。
*read ->
结合DictReader,读取csv。
*seek ->
根据图片的名字 与 图片所在目录,获取文件的绝对地址。
get_coding ->
根据文件后缀,决定open()的模式;
utf-8 :不支持中文 ;utf-8-sig :支持中文。
Ⅱ、tkinter的屏幕UI ,实现编码环境:(其实一般不需要)
(1):思路
①:新建新项目,读取老项目。
②:若是新项目,需要新建csv,插入“头文字”。
③:若是老文件,需要呈现所有以前的文件名,选择后还需能读取。
(2):实现:
from tkinter import Tk
from tkinter import ttk
from tkinter import *
class TkScreen(Tk):
def __init__(self ,
* ,
title:str ,
size:list[int]
) -> NoReturn:
super(TkScreen ,self).__init__()
self.title(title)
self.geometry('x'.join(list(map(str ,size))))
def menu(self) -> NoReturn:
self.first_menu:Menu = Menu(self)
self.config(self.first_menu)
self.second_menu:Menu = Menu(self.first_menu)
self.second_menu.add_command(label="新建" ,command=lambda : self.create)
self.second_menu.add_command(label="打开" ,command=lambda : self.read)
self.second_menu.add_command(label="退出" ,command=lambda : self.destroy)
self.first_menu.add_ascade(label="目录")
def create(self) -> NoReturn:
pass
def read(self) -> NoReturn:
pass
Ⅲ、Pygame屏幕的实现:
***游戏逻辑的***:
一款视觉小说,需要包含:
1、back 背景(一个)
2、main 人物(一个或多个)
3、text 文字(一大条或一小条)
4、song 音乐(一段又一段)
5、effect 音效(一次又一次)
6、self 个性化游戏方式
所以说:
我们的csv文件,需要包含以上“头文字”,以此通过字典Dict来进行读取。
最终我们获得的数据,也一定是 list[dict] 的。
def main():
data:list[dict]
show_back:Callable ; back_x:int ; back_y:int
show_main:Callable ; main_x:int ; main_y:int
show_text:Callable ; text_x:int ; text_y:int
show_song:Callable
run:bool = True
pointer:int = 0
while run:
show_back(data[pointer]["back"] ,back_x ,back_y)
show_main(data[pointer]["main"] ,main_x ,main_y)
show_text(data[pointer]["text"] ,text_x ,text_y)
show_song(data[pointer]["song"])
pygame.display.flip()
for event in pygame.event.get():
match event:
case pygame.QUIT:
run = not run
break
case pygame.KEYDOWN:
pointer += 1
case _:
pass
PS:这只是思路,实际上需要自己 "添砖加瓦"。
不喜勿喷,只是分享新东西,支持有人根据这个思路去创造应用。
2024/4/4
在校 无事 平安