前排提示:学习这个之前,你可以先去学习一下tkinter
(ACG圈的朋友可以选择跳过这里…)
Galgame(日文假名:ギャルゲーム,平文式罗马字:Gyaru Gēmu,又称美少女游戏)是一种玩家可以与动画美少女进行互动的电子游戏,其受众主体是男性,galgame的游戏类型大多数是vng(视觉小说)但是也有交互式的galgame。
美少女游戏是特属于日本文化的现象;在美国或欧洲的电玩工业中,少有类似的游戏类型存在。美少女游戏占据相当大的日本市场,是日本个人电脑电子游戏的大宗;不过,由于确实存在的文化差异,只有小部分此类游戏被翻译成为其他语言(主要是英文和中文)版本。
对于游戏运行的实际画面(样品),你可以前往:https://www.bilibili.com/video/av90715146去观看
开源程序放在这里的:https://download.csdn.net/download/tc9527_/12180013
本文章就是通过开发这些来实现Galgame的建立,这是之前写的可能有些Bug…
Galgame有三大要素:
立绘: 包含人物立绘与场景立绘;
音乐:音效与背景音乐
剧本:人物的对白与诸多的旁白描写
相信大部分的小伙伴对于原画与音乐这一方面还不是太擅长,所以在这里推荐一些 网站,可以创建角色:
AI捏脸: https://artbreeder.com/_可以实现人物的组合与捏脸,不需要美工技巧.
(需要科学上网.)
背景(开放版权_运行商用_详见网站说明)_ 可以下载一些背景充当游戏背景.
音乐制作:https://learningmusic.ableton.com/
程序使用了tkinter 的 resizable 方法来不允许窗口随意更改大小,所以我们对于程序背景采取了强制的px大小,这里是我采用的像素大小
背景: 960*542 px
人物头像:139146 px**
根据这个大小我们可以来建立窗口.(当然你也可以不拘束于我的px大小,你可以将其改为1920*1080都可以.)
如果你是在网上搬运下来的图片,有苦于图片大小不一致,可以在Windows自带画图程序中修改分辨率,当然你也可以用PIL来实现全屏后实时的分辨率转换(这款游戏就没有这么做了,因为这么作会使我得图片有一定的失真)
from PIL import Image
im = Image.open('你的图片地址')
im.save(r'/home/uftp/jia/'+city+'.jpg',dpi=(300.0,300.0))
对于剧本的保存,我们使用了json来保存,并且使用了列表来存储剧本,以下便是列表的格式:
# 文件: begin.json
[
[
{
"imgae":"客厅", # 规定背景图片,会默认在其后面添加.png
"music":"欢快的", # 规定背景音乐,会默认在其后添加.wav
"title":"第一章" # 游戏的章节标题
},
[
["人物名称","对白"], # 人物与对白
["人物名称","对白"],
["无","对白"], # 这个一般用于内心独白
["音乐","悲伤的"], # 切换音乐,这个也可以用于声优的配音
["人物",[['开始','begin'],['结束','伤心']]] # 选择分支,[['开始','开心'],['结束','伤心']]中,以
#['开始','begin']为例子 开始 为选择时展示的文本,开心指的是,选择该分支时所进行的剧本名称,后缀是json
]
]
]
# 伤心.json
[
[
{
"image":"街道",
"title":"第二章第一节",
"music":"快乐的"
},
[
["人物",'对白'],
["人物名称","对白"],
["人物名称","对白"],
["人物名称","对白"],
['end','end_1',':普通结局'] # 结尾展示 ['end','音乐','结局显示文本']
]
]
],
[
]
'''展示end字幕'''
end = '''
配音:
XXX - XXX
XXX - XXX
XXX - XXX
'''
import json
with open("end.json",'w') as f:
json.dump(end,f)
在开始编程之前,我们先来看看今天需要导入一些什么包或者库
首先是 tkinter,用于实现窗口对象的建立与UI的美化
还有就是 tkinter.font 的Font虽然也是属于tkinter但是我还是不得不提一下,这个包是 对tkinter的文本的设置,下列是他的简单代码
import tkinter
from tkinter.font import Font
ft = Font(size=12,family="幼圆") #size 是字号参数,family 是字体参数
tkinter.Label(text = "开始",font=ft).pack() # 字体修改
import pygame
pygame.init() # 我们在使用pygame大部分功能前都要将其初始化的哟
sound_yinxiao = pygame.mixer.Sound(r'./Gamedata/adi/Caidan.wav')
sound_yinxiao.play() # 播放
sound_yinxiao.stop() # 暂停
我们现在背景图片文件目录中创建一个background.png的图片,大小为960*542 px ,可以参照以下的图片(最好最右侧是纯色)
再创建一个类似这样的图片,命名为XW.png(px:334*152)(建议背景为纯色):
以上就是程序所需要的图片,接下来打开网易云或者其他的音乐播放器,下载一首你认为可以作为开始菜单的背景音乐,放在音乐的文件夹下,改名为 Caidan.wav,记得将音频文件改为wav格式的哟,否则pygame会生闷气而报错的.
(使用剪辑软件或者格式工厂可以修改后缀名)
运行的效果:
好了,我们先来写写代码:
import pygame,json
import tkinter as tk
import tkinter.font as tf
from PIL import Image
pygame.init()
def RGB_to_Hex(tmp): # tkinter 的 bg 采用的是十六进制来表示颜色,所以我们要将其转化为16进制
# 这段代码来自于https://blog.csdn.net/Forter_J/article/details/89145794
rgb = tmp.split(',') # 将RGB格式划分开来
strs = '#'
for i in rgb:
num = int(i) # 将str转int
# 将R、G、B分别转化为16进制拼接转换并大写
strs += str(hex(num))[-2:].replace('x', '0').upper()
return strs
class Windows(): # 窗口对象
def __init__(self):
self.Sound = None # 这个变量用于设置背景音乐,诸如 pygame.mixer.Sound("背景音乐") 就是在这里建立
self.nowSound = None # 这个变量用于设置当前正在播放的音乐名称,
# 用于游戏中途前往界面(程序终止了当前的音乐,换了碟),在回来后,播放之前的音乐
self.Sound_yinxiao = None # 设置播放的音效,诸如 pygame.mixer.Sound("背景音效")
def Main(self):
self.root = tk.Tk()
# 以下是对音乐的设置
self.Sound = pygame.mixer.Sound('./Gamedata/adi/Caidan.wav') # 设置音乐
self.Sound.play() # 开始你的表演SHOW
# 以下是图片的设置,只能在实例化Tk对象后创建,在__init__中创建会报错,并且他必须是全局变量,否则后期会出现Bug.
self.Background=tk.PhotoImage(file=r'./Gamedata/pic/UI_菜单.png')
tk.Label(image=self.Background).place(relheight=1, relwidth=1) # 放置背景图片控件,你也可以是用Canvas来放置图片
# 以下是对窗口的设置
self.root.title("这是窗口的游戏名称")
self.root.geometry("960x540") # 960x540,x是字母!
self.nowSound = "Caidan" # 将now修改为音乐文件的文件名,没有后缀
self.root.resizable(False,False)
im = Image.open(r'./Gamedata/pic/UI_菜单.png')
RGB = im.getpixel((650,100))[0:3] # 获取放置开始与继续游戏的像素RGB
print(RGB)
im.close()
Font = tf.Font(family="幼圆",size=30) # 设置字体
newStart = tk.Label(text="开始游戏",font=Font, bg = RGB_to_Hex("%s,%s,%s" % (RGB[0], RGB[1], RGB[2])),fg="#FD3C5E")
newStart.place(x=650,y=100)
nextPlay = tk.Label(text="继续游戏",font=Font,bg=RGB_to_Hex("%s,%s,%s" % (RGB[0], RGB[1], RGB[2])),fg="#FD3C5E")
nextPlay.place(x=650, y=300)
self.root.mainloop()
if __name__ == '__main__':
Windows().Main()
这样我们就实现了开始菜单的界面设置,但是这只是一副空壳,没法真正的运行,我们需要给两个Label绑定属于它们的事件.
但是,我们接下来要去捣鼓一个 选择对话框,类似于tkinter.message.askquetion的选择对话框,但是我们的对话框长这样。(可以自由选择哟)
来让我们为Windows类添砖加瓦吧!XunWen方法建立.
import pygame,json
import tkinter as tk
import tkinter.font as tf
from PIL import Image
pygame.init() # 初始化pygame
def RGB_to_Hex(tmp): # tkinter 的 bg 采用的是十六进制来表示颜色,所以我们要将其转化为16进制
# 这段代码来自于https://blog.csdn.net/Forter_J/article/details/89145794
rgb = tmp.split(',') # 将RGB格式划分开来
strs = '#'
for i in rgb:
num = int(i) # 将str转int
# 将R、G、B分别转化为16进制拼接转换并大写
strs += str(hex(num))[-2:].replace('x', '0').upper()
return strs
class Windows(): # 窗口对象
def __init__(self):
self.Sound = None # 这个变量用于设置背景音乐,诸如 pygame.mixer.Sound("背景音乐") 就是在这里建立
self.nowSound = None # 这个变量用于设置当前正在播放的音乐名称,
# 用于游戏中途前往界面(程序终止了当前的音乐,换了碟),在回来后,播放之前的音乐
self.Sound_yinxiao = None # 设置播放的音效,诸如 pygame.mixer.Sound("背景音效")
def XunWen(self,QUE,YesQ="确定",NoQ="不要",EY=None,EN=None,argY=None,argN=None):
'''YesQ是确定按钮的文本,QUE是询问文本,NoQ是否认按钮的文本,EY是确定按钮后执行的操作,EN是否认的操作'''
# 属性设置
def pa():
pass
if EY == None:EY = pa
if EN == None:EN = pa
# 如果没有传入EY或者EN两个参数,则默认其没有多余的操作,只是单纯的关闭按钮
self.XWW = True # 告诉程序已经打开了对话框,再去启动其余的对话框时无效的(木大木大木大)
tf_Title = tf.Font(size=10)
tf_XW = tf.Font(size=20)
self.pic_XW = tk.PhotoImage(file=r'./Gamedata/pic/XW.png')
# 因为这只是一个对话框说一没有必要去修改窗口背景对象,但是还是要设置为全局变量!
# 窗口设置
label = tk.Label(image=self.pic_XW)
label.place(x=270,y=160)
im = Image.open("./Gamedata/pic/XW.png")
RGB = im.getpixel((1, 1))[0:3]
Color_16 = RGB_to_Hex("%s,%s,%s" % (RGB[0], RGB[1], RGB[2]))
a3 = tk.Label(text="%s"%(QUE),font=tf_Title,bg=Color_16)
a3.place(x=380,y=225)
Yes = tk.Label(text=YesQ,font=tf_XW,bg=Color_16)
Yes.place(x=340,y=255)
No = tk.Label(text=NoQ,font=tf_XW,bg=Color_16)
No.place(x=450,y=255)
def re():
self.XWW = False # 告诉系统你关闭了对话框,接下来你又可以肆意点开他了
label.destroy()
a3.destroy()
Yes.destroy()
No.destroy()
def Tr(e):
re()
if argY == None:
EY()
else:
EY(argY)
def Fr(e):
re()
if argN == None:
EN()
else:
EN(argY)
Yes.bind("" ,Tr)
No.bind("" ,Fr)
def Start(self,event=0):# 因为可能为绑定的事件对象,所以需要一个event参数
self.XunWen(QUE="是否开始新游戏?",NoQ="不可!",YesQ="允许!") # 暂时不绑定EY
def Main(self):
self.root = tk.Tk()
# 以下是对音乐的设置
self.Sound = pygame.mixer.Sound('./Gamedata/adi/Caidan.wav') # 设置音乐
self.Sound.play() # 开始你的表演SHOW
# 以下是图片的设置,只能在实例化Tk对象后创建,在__init__中创建会报错,并且他必须是全局变量,否则后期会出现Bug.
self.Background=tk.PhotoImage(file=r'./Gamedata/pic/UI_菜单.png')
tk.Label(image=self.Background).place(relheight=1, relwidth=1) # 放置背景图片控件,你也可以是用Canvas来放置图片
# 以下是对窗口的设置
self.root.title("这是窗口的游戏名称")
self.root.geometry("960x540") # 960x540,x是字母!
self.nowSound = "Caidan" # 将now修改为音乐文件的文件名,没有后缀
self.root.resizable(False,False)
im = Image.open(r'./Gamedata/pic/UI_菜单.png')
RGB = im.getpixel((650,100))[0:3] # 获取放置开始与继续游戏的像素RGB
print(RGB)
im.close()
Font = tf.Font(family="幼圆",size=30) # 设置字体
newStart = tk.Label(text="开始游戏",font=Font, bg = RGB_to_Hex("%s,%s,%s" % (RGB[0], RGB[1], RGB[2])),fg="#FD3C5E")
newStart.place(x=650,y=100)
nextPlay = tk.Label(text="继续游戏",font=Font,bg=RGB_to_Hex("%s,%s,%s" % (RGB[0], RGB[1], RGB[2])),fg="#FD3C5E")
nextPlay.place(x=650, y=300)
newStart.bind("" ,self.Start)
# nextPlay.bind()
self.root.mainloop()
if __name__ == '__main__':
Windows().Main()
好了,这就是开始界面的建立了,因为游戏还没有完全的开发,所有有些函数或者绑定现在先空在那里,接下来的代码会逐步的完善与优化,那,我们继续吧.