真的想看 C++ 代码?好吧,我相信你看完下面这些之后,想法会有所改变的
// 以下代码未测试!!懒得找编译器了(因为使用了 TCHAR,不好用 gcc
class Image {
public:
TCHAR* m_name;
TCHAR* m_path;
int m_index;
TCHAR* m_bgm;
Image(TCHAR* name, TCHAR* path, int index) {
m_name = _tcsdup(name);
m_path = _tcsdup(path);
m_index = index;
}
~Image() {
free(m_name);
free(m_path);
}
};
class Character {
public:
POINT m_location;
TCHAR* m_name;
int m_index;
Image** m_cg; // use pointer here
int m_cgLen
Character(POINT location, TCHAR* name, int index, Image** cg, int cgLen) {
m_location = location;
m_name = _tcsdup(name);
m_index = index;
// copy CGs
m_cg = new Image *;
m_cgLen = cgLen;
for (int i = 0; i < m_cgLen; i ++) {
Image *c = cg;
m_cg = new Image(c->m_name, c->m_path, c->m_index);
}
}
~Character() {
free (m_name);
//
for (int i = 0; i < m_cgLen; i ++) {
delete m_cg;
}
}
};
class Selection {
public:
TCHAR* m_context;
int m_index;
int m_jumpSceneIndex;
Selection(TCHAR* context, int index, int jumpSceneIndex) {
m_context = _tcsdup(context);
m_index = index;
m_jumpSceneIndex = jumpSceneIndex;
}
~Selection() {
free(m_context);
}
};
class Word {
public:
int m_type;
Selection** m_selections;
int m_selectionLen;
Word(int type, TCHAR** contextArray, int* indexArray, int* jumpSceneIndexArray, int arrayLen) {
m_selections = new Selection;
m_selectionLen = arrayLen;
for (int i = 0; i < m_selectionLen; i ++) {
m_selections = new Selection(contextArray, indexArray, jumpSceneIndexArray);
}
}
~Word() {
for (int i = 0; i < m_selectionLen; i ++) {
delete m_selections;
}
}
};
class Scene {
public:
TCHAR* m_name;
int m_index;
Image** m_bg;
Character** m_characters;
};
ofz 发表于 2014-9-10 13:16
真的想看 C++ 代码?好吧,我相信你看完下面这些之后,想法会有所改变的
// 以下代码未测试!! ...
看出来了。。。可以这样。。。
C++是给别人看的。。。
引擎需要注意的
图片素材的处理,OpenGL需要掩模纹理,因此图片是双份。或许可以使用代码进行处理。
窗口大小及分辨率的处理。
资源是否需要打包。
按键控制的处理。
兼容性。
目标是读取资源配置文件,也就是脚本?并按照编号和键盘控制运行。脚本需要在程序加载中读取完毕,对于设置可以在主进程启动之前用一个窗口设置,并存储配置文件。(设置中可以设定脚本文件位置)
最好是单文件,如果需要.NET框架统一用4.0版本。如果是C++请确保可以在XP上运行。
另需要讨论图片的位置定义方法,以及版权页的处理办法,还有过渡特效的处理,还有如何留后期扩充的余地
ofz 发表于 2014-9-10 13:16 static/image/common/back.gif
真的想看 C++ 代码?好吧,我相信你看完下面这些之后,想法会有所改变的
// 以下代码未测试!! ...
C++的话还是直接上Qt比较愉快
于10.14修改……再度思考:这个是我这个版本的……
取消文字定义的编号,其编号自动从0开始。
对于存档文件,应独立出来。存档读档界面也是按照场景定义,因此这些特殊的场景定义最好是单独的文件。并且场景编号也是特殊的。
对于游戏角色的处理,还是取消Character类,直接调用图片。
当前脚本读取函数的难点是两个及以上参数的读取……等待解决……其实文字定义取消编号的原因也是这个……角色定义也是……大概有头绪了……这样:(变成汇编语言来啦
选择 [内容]
跳转 [场景编号]
本帖最后由 drzzm32 于 2014-10-14 23:06 编辑
来看看我这奇特的算法。。。
脚本有变!现在是汇编格式。。。
Public Class AVG
Public Class Image
Public Path As String
Public Index As Integer
End Class
Public Class PicObj
Public Location As Single 'Can use Enum
Public IMG As Image
End Class
Public Class Selection
Public Context As String
Public JumpSceneIndex As Integer
End Class
Public Enum WordType
Comment
Script
Title
GameRun
Saving
Loading
End Enum
Public Class Scene
Public Name As String
Public SceneIndex As Integer
Public BG As Image
Public CG() As PicObj
Public BGM As String
Public WordType As WordType
Public Choices() As Selection
End Class
Private Enum ScriptHead
NULL
StartSceneDim
EndSceneDim
Background
BGM
StartCGDim
EndCGDim
CGPath
CGLocation
StartWordDim
Choice
Jump
EndWordDim
End Enum
Public Function LoadScript(ByVal Path As String) As Scene()
Dim SceneTmp() As Scene = Nothing
Dim SceneIndexTmp As Integer = Nothing
Dim CGIndexTmp As Integer = Nothing
Dim ChoiceAutoIndexTmp As Integer = Nothing
Dim StartPath As String = Application.StartupPath & "\" '获取当前位置
Dim Head As ScriptHead = ScriptHead.NULL '定义脚本头
Dim LineBreak As Integer = 10 '设定换行符
Dim Size As Long = Microsoft.VisualBasic.FileIO.FileSystem.GetFileInfo(Path).Length '获取文件大小
Dim CookedString As String = "" '定义已处理字符串变量
Dim Strings As String = Microsoft.VisualBasic.FileIO.FileSystem.ReadAllText(Path) '读取文件
Dim Steps As Integer = Strings.Length '获取字符串长度
Dim x As Integer = 0, y As Integer = 0 '定义循环控制变量
Do Until x >= Steps '检测是否读到文件结尾
Do Until Strings.Chars(x) = " " Or Strings.Chars(x) = Chr(LineBreak) '检测是否读到空格或行结尾
CookedString = CookedString & Strings.Chars(x) '存入已处理字符串变量数组
x = x + 1 '下一个字符
If x = Steps Then '这个String的编号(String.Chars(Integer))是从0开始的,这里防止数组越界。
GoTo EndFlag '即字符数为Num的字符串其编号为0到Num-1,上面的+1实际已经超出界限,这里检
End If '测并跳出。
Loop
Select Case Head
Case ScriptHead.NULL
Select Case CookedString
Case "开始定义场景"
Head = ScriptHead.StartSceneDim
Case "结束定义场景"
Head = ScriptHead.EndSceneDim
Case "背景"
Head = ScriptHead.Background
Case "音乐"
Head = ScriptHead.BGM
Case "开始定义立绘"
Head = ScriptHead.StartCGDim
Case "结束定义立绘"
Head = ScriptHead.EndCGDim
Case "立绘地址"
Head = ScriptHead.CGPath
Case "立绘位置"
Head = ScriptHead.CGLocation
Case "开始定义文字"
Head = ScriptHead.StartWordDim
Case "选择"
Head = ScriptHead.Choice
Case "跳转"
Head = ScriptHead.Jump
Case "结束定义文字"
Head = ScriptHead.EndWordDim
End Select
Case ScriptHead.StartSceneDim
SceneIndexTmp = CInt(CookedString)
SceneTmp(SceneIndexTmp).SceneIndex = SceneIndexTmp
Head = ScriptHead.NULL
Case ScriptHead.EndSceneDim
SceneTmp = Nothing
Head = ScriptHead.NULL
Case ScriptHead.Background
SceneTmp(SceneIndexTmp).BG.Path = StartPath & CookedString
SceneTmp(SceneIndexTmp).BG.Index = SceneIndexTmp
Head = ScriptHead.NULL
Case ScriptHead.BGM
SceneTmp(SceneIndexTmp).BGM = StartPath & CookedString
Head = ScriptHead.NULL
Case ScriptHead.StartCGDim
CGIndexTmp = CInt(CookedString)
SceneTmp(SceneIndexTmp).CG(CGIndexTmp).IMG.Index = CGIndexTmp
Head = ScriptHead.NULL
Case ScriptHead.EndCGDim
CGIndexTmp = Nothing
Head = ScriptHead.NULL
Case ScriptHead.CGPath
SceneTmp(SceneIndexTmp).CG(CGIndexTmp).IMG.Path = StartPath & CookedString
Head = ScriptHead.NULL
Case ScriptHead.CGLocation
SceneTmp(SceneIndexTmp).CG(CGIndexTmp).Location = CSng(CookedString)
Head = ScriptHead.NULL
Case ScriptHead.StartWordDim
ChoiceAutoIndexTmp = 0
Select Case CookedString
Case "对话"
SceneTmp(SceneIndexTmp).WordType = WordType.Comment
Case "读档"
SceneTmp(SceneIndexTmp).WordType = WordType.Loading
Case "存档"
SceneTmp(SceneIndexTmp).WordType = WordType.Saving
Case "旁白"
SceneTmp(SceneIndexTmp).WordType = WordType.Script
Case "标题"
SceneTmp(SceneIndexTmp).WordType = WordType.Title
Case "启动"
SceneTmp(SceneIndexTmp).WordType = WordType.GameRun
End Select
Head = ScriptHead.NULL
Case ScriptHead.Choice
SceneTmp(SceneIndexTmp).Choices(ChoiceAutoIndexTmp).Context = CookedString
Head = ScriptHead.NULL
Case ScriptHead.Jump
SceneTmp(SceneIndexTmp).Choices(ChoiceAutoIndexTmp).JumpSceneIndex = CInt(CookedString)
ChoiceAutoIndexTmp = ChoiceAutoIndexTmp + 1
Head = ScriptHead.NULL
Case ScriptHead.EndWordDim
ChoiceAutoIndexTmp = 0
Head = ScriptHead.NULL
End Select
If Strings.Chars(x) = " " Or Strings.Chars(x) = Chr(LineBreak) Then '检测是否读到行结尾
x = x + 1
End If
Loop
EndFlag:
Return SceneTmp
End Function
End Class
脚本变成了这样。。。'开始定义场景 [场景编号] [场景名,仅作注释,可用于Debug]
' [元素定义]
'结束定义场景
'[背景/音乐] [地址]
'开始定义立绘 [立绘名,仅作注释,可用于Debug]
' 立绘地址 [地址]
' 立绘位置 [位置]
'结束定义立绘
'开始定义文字 [对话/旁白/标题/存档/读档/启动]
' 选择 [内容]
' 跳转 [场景编号]
'结束定义文字
然后是某Readme。。。#NOTICE OF THE ENGINE#
场景编号需要手动设置。
背景为单一背景。
立绘编号需要手动设置,,目的是区分多立绘的情况。
文件路径(即地址)为:【Audio\audio.wav】
文字定义中,脚本顺序即为显示顺序,选择在前,跳转在后,两者紧挨,一个文字定义中选择数目和跳转数目相同。
某些特殊场景,应当使用诸如“0”、“1”、“2”、“3”这种场景编号,并置于独立的文件中。
脚本文件的建立,最好分为配置文件(启动画面,标题画面),存档文件(存档画面,读档画面),游戏脚本。
本帖最后由 漆黑之翼 于 2014-10-15 00:25 编辑
drzzm32 发表于 2014-10-14 23:04 static/image/common/back.gif
来看看我这奇特的算法。。。
脚本有变!现在是汇编格式。。。
你这case写得太蛋疼了……到时候越写越长这函数就没法看了。我觉得还是先把这一行的参数收集完。然后根据操作直接转调对应函数,把参数列表塞进去就好了。类似这样:str = File.ReadLine();
args = str.split(' ');
oper = parseHeader(args)
switch (oper)
{
case xxx:
DoXXX(args);
break;
case yyy:
DoYYY(args);
break;
}
然后每个操作里面要用多少个参数要怎么做,就是那个操作自己要关心的事了。
本帖最后由 drzzm32 于 2014-10-15 08:12 编辑
漆黑之翼 发表于 2014-10-15 00:20
你这case写得太蛋疼了……到时候越写越长这函数就没法看了。我觉得还是先把这一行的参数收集完。然后根据 ...
大概明白你的说法了……
把一条语句以空格为分隔符读入数组,检测数组0号元素,用case跳到相应函数把数组的参数塞入类……嗯……完全可以……
然后,你觉得脚本格式这样弄,如何?
实际上要是你没事做的话,你也可以来干这个的……本来就是一个对论坛公开的项目……
drzzm32 发表于 2014-10-15 08:11 static/image/common/back.gif
大概明白你的说法了……
把一条语句以空格为分隔符读入数组,检测数组0号元素,用case跳到相应函数把数 ...
脚本格式的话,我个人觉得还是简洁点比较好,毕竟关键字太长的话打起来麻烦。Begin-End格式的话适合出现嵌套的时候。我自己也设想过用xml做脚本:<?xml version="1.0" encoding="utf-8"?>
<!--根节点-->
<engine>
<var name="test" value="1" />
<segment id="0">Hello World!</segment>
<jump target="2" />
<segment id="1">jump failed</segment>
<segment id="2">this is a jump test</segment>
<switch saveto="test2">
<case idx="0">choosen 0</case>
<case idx="1">choosen 1</case>
<case idx="2">choosen 2</case>
</switch>
<if condition="test2 == 1">
<segment id="3">now the value of "test2" is 1</segment>
</if>
<jump file="xml_design.xml" />
</engine>
我的话参加下讨论还好,真让我写的话不一定有那么多时间,白天还要上班呢。况且我自己还挖了坑没填,再者VB我也用不惯。
其实你这个不怕被人看的话也可以放Github嘛,或者要中文的话放CSDN的Code(虽然我没用过)也可以。我自己的坑就在Github上。
本帖最后由 漆黑之翼 于 2014-10-15 22:01 编辑
漆黑之翼 发表于 2014-10-15 20:37 static/image/common/back.gif
脚本格式的话,我个人觉得还是简洁点比较好,毕竟关键字太长的话打起来麻烦。Begin-End格式的话适合出现嵌 ...
也不是为啥啦,跟正不正式没关系,只是存档方便,不用担心弄丢或者换电脑。
而且一不小心写错了还可以一键还原。不小心点成回复了。