github申请学生免费5个私有repo的方法

昨天才发现github上
https://github.com/edu 这里可以申请学生免费的私有micro账号,即免费的5个私有repo(原价7美元1个月)
于是大地试了试,没想到瞬间通过了

Untitled

申请的时候最好给待申请的github账号绑定个学校的带edu的邮箱这样很快就能申请成功并选上,大地用的学院的个人邮箱。
year那栏就填写学习的总年数,比如大地是大三那就是15……(吧?)
然后申请理由……大地填的是放毕业设计

然后就收到了!虽然邮件被奇怪地分类在了被屏蔽的邮件中……

Hey Windy Darian, we have awesome news…

We’ve upgraded you to a student micro account, which will be free for the next two years. We don’t have any collaboration limits, so any group projects you may encounter can be hosted via your account.

Spread the word — we love giving free micro accounts to students! Send them to: https://github.com/edu

Have an Octotastic day!

再次打开新建repo的界面,现在已经可以创建私有repo了!

Untitled2

于是终于有地方放游戏本体了喵。

Sogal自定义脚本——SogalScript!

Sogal是大地无敌正在坑的Gal引擎
那么 一套脚本是并不可少的 所以就有了SogalScript
应该算是一套自定义脚本格式(嗯大概还没到语言的完备程度而且都是依托于python实现的)
(嘛窝觉得它的一个亮点是可以通过:和:识别说话者
刚刚才把if判断语句添加进去的说……
这是一个SogalScript脚本文件的示例:

ifselectionjumptest.sogal

#这个应该和selectionjumptest效果一样 不过引入了if!
#不再像汇编语言一样讨厌了!
@mark:start
@bg testbg2,qp luc_naked_trueheart -0.33 0
D4的路西菲尔:
「现在是做出抉择的时间呢……」

@choice D4的路西菲尔:撒,做出选择吧 , qp luc_naked_trueheart -0.33 0
上发条
--不上发条
选你妹啊!
--啊哈!?

@if last_choice == 0
    
    @qp luc_naked_desire 0.33 0
D4的路西菲尔:
「从这里跳转到各种测试试试?」

    @choice
图像测试(jump)
脚本测试(jump)
音效测试(jump)
文本框测试(expand)
图像测试(expand)

    @if  last_choice == 0
    @script
story_manager.beginScene('imagetest')
    @elif last_choice == 1
    @jump scripttest
    
温蒂达莉安:
「这条语句不会出现!」
    @elif  last_choice == 2
    @jump soundtest
    
温蒂达莉安:
「这条语句也不会出现!」
    @elif last_choice == 3
        @expand textboxtest  #嘛虽然没必要缩进
        @qp luc_naked_normal -0.33 0
D4的路西菲尔:
「刚才发生了什么……现在因为expand继续执行了呢。刚才是一个文本框测试」
        @goto start
    @elif last_choice == 4
        @expand imagetest
        @qp luc_naked_normal -0.33 0
D4的路西菲尔:
「刚才发生了什么……现在因为expand继续执行了呢。刚才是一个图像测试」
        @goto start
    @end

@elif last_choice == 2
谜の音:选这个是不行的哦,回到开头吧
    @goto start

@end

说明什么的

==================================================================

脚本在scene中以.sogal格式存储
注意文件编码统一用UTF-8
而且最好不要用Windows记事本直接编辑因为它存的UTF8好像会有奇怪的标记然后
别的系统可能不认
(嘛窝这边是Visual Studio和Eclipse都用的
音乐音效,以16位wav或ogg格式存储,因为使用的音频引擎仅仅是openal能力有限……

关于资源的放置:
图片(背景、立绘、CG)应以png24形式放在images中
anm 播放的panda3D egg格式2d动画也应放在images中
所有声音相关资源在audio中

备忘:
转义符
__在行前可以表示这是一个文本中的空行
: :表示这是一个英文或中文冒号而不是名称表达的简化形式
# 表示是#而非注释

命令列表 
命令写在命令段中(整个命令段以@开头 命令段中以,分隔不同的命令)
注意文件名都不能加空格,以后会考虑能用引号包含

TODO:在StoryManager中实现背景、立绘、声音的支持,注意要考虑到要从某个存档文件中读取背景和立
绘的情况

已实现
文本:
name = -Name    设置名字 可以有空格
name -Name   设置名字 可以有空格
文本段中开头-Name: 或-Name:(中文冒号)  设置名字的简化形式
textboxstyle normal/large 改变文本框格式,会清空文本
p 格式中用来清空已有字符 ,large文本框用,注意和显示图片的p的区别是它不带任何参数
textbox -propname -content 改变文本框属性,content可以有空格,会在脚本命名空间中eval计算(也就是如果是字符串要加引号),参考game_text_box.py中GameTextBox.properties
textbox apply 应用文本框属性的修改,会清空文本

场景:
p -key -fileName -x -z (-s) (-fadein)  在指定位置显示立绘位置 0 0表示正中  1 1表示右上 注意除了Location都不能有空格 -相同的Keyword会直接替换  fadein是淡入                       
p -key -fileName 显示立绘,如果已存在,其会在当前位置用新图片替代-否则绘制在正中
bg -FileName  立即改变背景
bg -FileName -Time 改变背景
ploc -key -x -y -z (-time)  改变立绘位置 Location应该是两个数字 x z(或是3个x y z)
ploc -key -x -z 
pcolor -key -r -g -b -a (-time)  rgba范围都在0到1
pscale -key -s (-time) 缩放 注意 以总是以这次缩放前的大小为1
del -key  移除立绘、o3d、o2d、pa
del -key -time 淡出并移除
o3d -key -fileName -x -y -z -r -g -b -a -sx -sy -sz 显示3D模型,x轴向由 y轴向屏幕内 z轴向上 大小自己看着办吧
o2d -key -fileName -x -y -z -r -g -b -a -sx -sy -sz 在3D中显示2D图片
pa -key -fileName -x -z -sx -sy (-f) 显示egg动画在前景注意动画要手动缩放宽高比
delbg 删除背景
delbg -time  淡出背景
qp -fileName -x -z   快速立绘!在进入下一个文本段时就会自动消失!
clear 重置场景。移除所有立绘,将背景设置为黑色。用于初始化和场景切换
clear -Time 重置场景。在一定时间内淡出到黑色
clear -Time -bgFileName 重置场景。以一定速度渐入到某个背景图片

声音:
v -FileName (-volume)语音
vstop    停止当前语音
se -FileName (-volume)播放音频(非语音的音效)
sestop    停止当前所有se播放的音效
bgm -FileName (-fadein) (-volume) (0) 循环播放音乐使用默认淡入淡出设置 fadein为淡入或音乐交换用时间(所有时间以秒为单位) 末尾的0作为参数表示不循环
bgmstop (-fadeout)    结束或淡出当前音乐,Time为淡出时间
env -FileName (-fadein) (-volume) (0) 循环播放环境音效 末尾的0作为参数表示不循环
envstop (-fadeout)	淡出环境音效
audiostop (-fadeout) 停止所有音效 BGM和ENV会淡出

功能逻辑:
mark: mark 标记以用于跳转,单独占一行命令
script   表示接下来的文本段是python脚本(注意其中不能有空行)
script -FileName 运行python脚本文件
注意: script脚本由专门的脚本命名空间执行 但在命名空间中请不要留下对任何panda3d物件的引用(否则可能影响序列化存档)
但是,下列引用的对象是可以在脚本空间中访问的(相对的)全局对象(参见story_manager.py中mapScriptSpace(self))
        script_global['goto'] = self.goto
        script_global['story_manager'] = self    
        script_global['game_text_box'] = self.gameTextBox
        script_global['story_view'] = self.storyView
        script_global['audio_player'] = self.audioPlayer
        script_global['gdict'] = self.script_space
另外因为Panda3D的关系(会在脚本的全局命名空间加一些无法被pickle序列化的C内容)和窝的一些小诡计所以全局命名空间不
会保存到存档文件中(但本地命名空间能保存和在下一段脚本中继承)所以使用global时要注意
——但,你可以把本地空间当成全局空间用……

choice 表示选择命令
头部有choice后,接下来的文本段每行是一个选择。
选择的结果会写入到脚本空间(本地)的last_choice变量中
第一个选项为0 第二个选项为1 以此类推
如果行开头是--则表示该选项不可用
另外select -text 可以为这个选项进行描述

goto -mark  跳转到标记
jump -FileName 读取sogal场景脚本并跳转(删除当前脚本队列)
expand -FileName 将sogal场景脚本展开到当前脚本(插入到当前脚本队列) expand命令语句只执行一次,将目标脚本插入到
当前队列后,自身也会消失

if condition 条件判断,单独占一行命令,注意冒号后接条件表达式(大概是为了以示区别吧 注意没有冒号
elif condition     你懂得,单独占一行命令
else          你懂得,单独占一行命令
end 结束当前if块 单独占一行命令

总之,再加上文本历史 自动播放 跳过已读文本 快进 隐藏界面 和简陋的主菜单——就可以一战了!

panda3d创建一个避免点到底层按钮的遮罩

编写游戏的时候经常要用到弹出游戏内对话框窗口什么的
而在弹出窗口时要禁用底层窗口的元素怎么办呢……
于是大地想到了一个跟HTML类似的方法,在窗口和下面之间加一个全透明遮罩层
遮罩层用DirectButton就能解决会按到下面的按钮的问题了

但是新的问题来了,在下面加DirectButton的话因为PGButton的特性会阻断Panda3d的事件
所以滚轮什么的也不能在弹出窗口用了

那么……只要让这个遮罩层能够重新发送滚轮和其他鼠标事件就可以了!

于是

#-*- coding:utf-8 -*-
'''
====================================================================================

   Copyright 2013, 2014 Windy Darian (大地无敌), Studio "Sekai no Kagami" 
   (世界之镜制作组) of Seven Ocean Game Arts (七海游戏文化社
   , 北京航空航天大学学生七海游戏文化社) @ http://sogarts.com

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

====================================================================================
Created on Apr 6, 2013
dialog mask
@author: Windy Darian
'''

from panda3d.core import NodePath,PGButton,MouseButton
from direct.showbase.DirectObject import DirectObject
import direct.gui.DirectGuiGlobals as DGG
from direct.gui.DirectButton import DirectButton

class DialogMask(DirectButton):
    '''used to generate a full-screen mask to prevent button-clicking below the focused window/dialog
    Added some tricks to make panda3d mouse events still available
    '''
    B1PRESS = PGButton.getPressPrefix() + MouseButton.one().getName() + '-'  
    B2PRESS = PGButton.getPressPrefix() + MouseButton.two().getName() + '-'  
    B3PRESS = PGButton.getPressPrefix() + MouseButton.three().getName() + '-'
    B4PRESS = PGButton.getPressPrefix() + MouseButton.four().getName() + '-'
    B5PRESS = PGButton.getPressPrefix() + MouseButton.five().getName() + '-'
    WHEELUP = PGButton.getReleasePrefix() + MouseButton.wheelUp().getName() + '-'
    WHEELDOWN = PGButton.getReleasePrefix() + MouseButton.wheelDown().getName() + '-'
    WHEELLEFT = PGButton.getReleasePrefix() + MouseButton.wheelLeft().getName() + '-'
    WHEELRIGHT = PGButton.getReleasePrefix() + MouseButton.wheelRight().getName() + '-'
    B1RELEASE = PGButton.getReleasePrefix() + MouseButton.one().getName() + '-'  
    B2RELEASE = PGButton.getReleasePrefix() + MouseButton.two().getName() + '-'  
    B3RELEASE = PGButton.getReleasePrefix() + MouseButton.three().getName() + '-'
    B4RELEASE = PGButton.getReleasePrefix() + MouseButton.four().getName() + '-'
    B5RELEASE = PGButton.getReleasePrefix() + MouseButton.five().getName() + '-'
    
    def __init__(self):
        DirectButton.__init__(self,parent = aspect2d, frameColor =(1,1,1,0), relief = DGG.FLAT,commandButtons = [])
        self.accept('window-event', self.windowResize)
        self.windowResize(None)
        #trick: make this re-throw mouse events
        self.bind(self.B1PRESS, self.rethrowEvent,['mouse1'])
        self.bind(self.B2PRESS, self.rethrowEvent,['mouse2'])
        self.bind(self.B3PRESS, self.rethrowEvent,['mouse3'])
        self.bind(self.B4PRESS, self.rethrowEvent,['mouse4'])
        self.bind(self.B5PRESS, self.rethrowEvent,['mouse5'])
        
        self.bind(self.WHEELUP, self.rethrowEvent, ['wheel_up'])
        self.bind(self.WHEELDOWN, self.rethrowEvent, ['wheel_down'])
        self.bind(self.WHEELLEFT, self.rethrowEvent, ['wheel_left'])
        self.bind(self.WHEELRIGHT, self.rethrowEvent, ['wheel_right'])
        
        self.bind(self.B1RELEASE, self.rethrowEvent,['mouse1-up'])
        self.bind(self.B2RELEASE, self.rethrowEvent,['mouse2-up'])
        self.bind(self.B3RELEASE, self.rethrowEvent,['mouse3-up'])
        self.bind(self.B4RELEASE, self.rethrowEvent,['mouse4-up'])
        self.bind(self.B5RELEASE, self.rethrowEvent,['mouse5-up'])
        
    def windowResize(self,arg):
        #Make this mask fill the screen
        self.reparentTo(aspect2d,sort = self.getSort())
        aspect = base.getAspectRatio()
        if aspect > 1:
            self['frameSize'] = (-aspect,aspect,-1,1)
        elif aspect: 
            hh = 1.0/aspect
            self['frameSize'] = (-1,1,-hh,hh)
            
    def setCommandButtons(self, *args, **kwargs):
        #inherited 
        pass
        
    def rethrowEvent(self,sevent,event):
        messenger.send(sevent)
        
                
    def destroy(self):
        self.ignoreAll()

在自定义窗体中,只要使用这个DialogMask类,在自定义窗体或对话框显示出时执行mask.show(),消失是执行mask.hide()就可以了

鼠标能正常点到前面的按钮,但点不到底层的按钮,鼠标滚轮滚动的事件也正常
鼠标能正常点到前面的按钮,但点不到底层的按钮,鼠标滚轮滚动的事件也正常

基于Panda3D的Galgame引擎/框架——Sogal开发中

这是大地无敌自己开发供自己的小伙伴们和北航七海游戏文化社用的galgame引擎——SOGAL(Seven Ocean Galgame Engine)
为什么要自己做呢?
因为大地的需求是要实现3D战斗场景的支持和一些2D3D混合的故事场景
用现成的gal引擎不太现实
于是选择了基于panda3d这个3D引擎,在这基础上再开发一个Galgame引擎
脚本控制示例
于是……今天脚本控制功能也实现了
脚本语言当然是python以及在这个基础上便于galgame流程制作的一套自定义剧本格式

GitHub的Repo在https://github.com/WindyDarian/Sogal
基于Apache License V2.0授权 基本上只要保留了版权声明和证书的原文件大家都可以用的说!

基本上再有主菜单选择枝存档之类的就可以成为第一版了
(但是果然还是好艰巨……

(当然预计的3D战斗系统并不算在这里面而是游戏的另外一个部分所以Apache License V2.0只限于这个框架本身。至于游戏本体用什么授权还没想好(逃

Panda3d 支持淡入淡出(Fading)的音频管理模块和类

嘛 因为需求音频的淡入淡出 但Panda3d默认不支持淡入淡出
于是就在Panda3d的基础上稍微写了一个支持淡入淡出的音频播放器模块
用了一些panda的Intervals,淡入淡出的效果还不错
还默认使用了loader后台读取的特性:)

from runtime_data import game_settings是窝的游戏设置,把相关的东西改成自己的后就可以直接用了!
AudioPlayer在Panda3D的ShowBase初始化之后再实例化即可

audio_player.py

#-*- coding:utf-8 -*-
'''
====================================================================================

   Copyright 2013, 2014 Windy Darian (大地无敌), Studio "Sekai no Kagami" 
   (世界之镜制作组) of Seven Ocean Game Arts (七海游戏文化社
   , 北京航空航天大学学生七海游戏文化社) @ http://sogarts.com

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

====================================================================================
Created on Jul 29, 2013
Audio manager.
@author: Windy Darian (大地无敌)@ http://www.agrp.info 
'''
from panda3d.core import AudioSound,AudioManager
from direct.showbase.DirectObject import DirectObject
from direct.interval.LerpInterval import LerpFunc
from direct.interval.FunctionInterval import Func,Wait
from direct.interval.IntervalGlobal import Sequence
from direct.stdpy.file import exists    #use panda3d's file API to support panda's virtual folder

from runtime_data import game_settings    #spec for my game

_fadeinIntervalTable = {}
_intervals = []

def play_audio(audio,fadein = 0, volume = 1, loop = False):
    '''plays an AudioSound'''
    if loop:
        audio.setLoop(True)
    if not fadein:
        audio.setVolume(volume)
        audio.play()
    else:
        interval = LerpFunc(_lerpAdjust, duration = fadein,
                            fromData = 0, toData = volume,
                            extraArgs = , blendType = 'easeOut')
        _fadeinIntervalTable = interval   
        _intervals.append(interval)    
            #save the interval in the table so if the audio stops during the interval it can stop the interval first
        audio.play()
        interval.start()
        
    
def stop_audio(audio,fadeout = 0):
    '''stops an AudioSound, instant or fade-out'''
    if _fadeinIntervalTable.has_key(audio):     #If the audio is currently on fade-in, then stop and remove the fade-in interval
        _fadeinIntervalTable.pause()
        _intervals.remove(_fadeinIntervalTable)
        del _fadeinIntervalTable
           
    if not fadeout:
        audio.stop()
    else:
        sequence = Sequence(LerpFunc(_lerpAdjust, duration = fadeout,
                                     fromData = audio.getVolume(), toData = 0,
                                     extraArgs = , blendType = 'easeIn'),
                            Func(audio.stop)
                            )
        sequence.start()  #reduce volume and stop the sound
        
        
def play(filepath, manager, loop = False, fadein = 0, volume = 1):
    '''load a sound in background, and play it when loading finishes'''
    loader.loadSound(manager,
                     filepath,
                     callback = play_audio,extraArgs = [fadein, volume, loop])    
    

def _lerpAdjust(volume,audio):
    '''Adjust the volume dynamiclly in fadein and fadeout'''
    audio.setVolume(volume)
    
_bgmMgr = None
_envMgr = None
_voiceMgr = None
_sfxMgr = None

class AudioPlayer(DirectObject):
    
    '''Audio Player class of Sogal
    usually there only need 1 instance
    '''
    def __init__(self):
        DirectObject.__init__(self)
        
        global _bgmMgr,_envMgr,_sfxMgr,_voiceMgr    
        '''if we already has an AudioPlayer instance,
           we just need to refer to the existing AudioManagers
           insead of creating some new ones'''
        if not _bgmMgr:
            _bgmMgr = AudioManager.createAudioManager()          #don't use ShowBase.musicManager for it can only play 1 music at the same time defaultly so it don't support cross-fade
            base.addSfxManager(_bgmMgr)
        if not _envMgr:
            _envMgr = AudioManager.createAudioManager()
            base.addSfxManager(_envMgr)
        if not _voiceMgr:
            _voiceMgr = AudioManager.createAudioManager()
            base.addSfxManager(_voiceMgr)
        if not _sfxMgr:
            _sfxMgr = AudioManager.createAudioManager()
            base.addSfxManager(_sfxMgr)
            
        self.bgmMgr = _bgmMgr
        self.envMgr = _envMgr
        self.voiceMgr = _voiceMgr
        self.sfxMgr = _sfxMgr 
        
        self.applySettings()
        
        self._currentBGM = None #to define there can only be one bgm
        self._currentENV = None # and one environment sound at the same time
        
        '''#test1 Load and play a music
        loader.loadSound(self.bgmMgr,
                         'audio/music/God-only-knows-Secrets-of-the-Goddess-.wav',
                         callback = play_audio,extraArgs = [3,1])
        '''
        '''#test2 A fade-out stop before the fade-in is completed
        sound = loader.loadSound(self.bgmMgr,'audio/music/God-only-knows-Secrets-of-the-Goddess-.wav')
        sq = Sequence(Func(play_audio,sound,10),Wait(5),Func(stop_audio,sound,5))
        sq.start()
        '''
        '''#test3  Load and play a music
        self.playBGM('church-organ-music', 2, 1, True)
        '''
        '''#test4 Another music before the fade-in is completed
        sq = Sequence(Func(self.playBGM,'audio/music/God-only-knows-Secrets-of-the-Goddess-.wav',10),
                      Wait(5),
                      Func(self.playBGM,'audio/music/church-organ-music.wav',10),
                      )
        sq.start()
        '''
        
    def applySettings(self):
        self.bgmMgr.setVolume(game_settings['music_volume']) #0.75
        self.envMgr.setVolume(game_settings['env_volume']) #0.75
        self.voiceMgr.setVolume(game_settings['voice_volume']) #1
        self.sfxMgr.setVolume(game_settings['sfx_volume']) #1
        
        
    def playVoice(self, path, volume = 1):    
        pathes = game_settings['voicepathes']
        types = game_settings['soundtypes']
        for ft in ((folder,type) for folder in pathes for type in types):
            if exists(ft[0] + path + ft[1]):
                path = ft[0] + path + ft[1]
                break
        play(path, self.voiceMgr, volume = volume)
    
    def playSound(self, path, volume = 1):
        pathes = game_settings['sfxpathes']  #example: ['audio/music','audio','']
        types = game_settings['soundtypes']  #example: ['.wav','.ogg','']
        for ft in ((folder,type) for folder in pathes for type in types):
            if exists(ft[0] + path + ft[1]):
                path = ft[0] + path + ft[1]
                break
        play(path,self.sfxMgr, volume = volume)
        
    def playBGM(self, path, fadein = 0, volume = 1, loop = True):
        if self._currentBGM:    #if there is a music playing then stop it
            self.stopBGM(fadein)
        pathes = game_settings['musicpathes']
        types = game_settings['soundtypes']
        for ft in ((folder,type) for folder in pathes for type in types):
            if exists(ft[0] + path + ft[1]):
                path = ft[0] + path + ft[1]
                break
        loader.loadSound(self.bgmMgr,
                     path,
                     callback = self._setAndPlayBGM,extraArgs = [fadein, volume, loop])    
    
    def playENV(self, path, fadein = 0, volume = 1, loop = True):
        if self._currentENV:
            self.stopENV(fadein)
        pathes = game_settings['envsoundpathes']
        types = game_settings['soundtypes']
        for ft in ((folder,type) for folder in pathes for type in types):
            if exists(ft[0] + path + ft[1]):
                path = ft[0] + path + ft[1]
                break
        loader.loadSound(self.envMgr,
                     path,
                     callback = self._setAndPlayENV,extraArgs = [fadein, volume, loop]) 
        
    def stopBGM(self, fadeout = 0):
        if self._currentBGM:
            stop_audio(self._currentBGM, fadeout)
        
    def stopENV(self, fadeout = 0):
        if self._currentENV:
            stop_audio(self._currentENV, fadeout)
    
    def stopVoice(self):
        self.voiceMgr.stopAllSounds()
    
    def stopSound(self):
        self.sfxMgr.stopAllSounds()
    
    def _setAndPlayBGM(self, audio, fadein, volume, loop):
        self._currentBGM = audio
        play_audio(audio, fadein, volume, loop)
        
    def _setAndPlayENV(self, audio, fadein, volume, loop):
        self._currentENV = audio
        play_audio(audio, fadein, volume, loop)
        
    

        

……嘛继续填坑去

Panda3D中会随窗口大小改变而改变宽高比的Camera实现方式(如何创建一个默认base.cam那样的Camera)

panda3d使用base.makeCamera(base.win)创建的Camera并不会随着窗体大小的改变而改变宽高比……于是到底怎样实现这样的Camera呢?
[省略一万字的口胡]
于是……这样就可以了……
在Showbase或者某个自定义的DirectObject中

from panda3d.core import Camera, Lens

创建相机时

self.cam1 = base.makeCamera(base.win)            #生成Camera
self.lens = PerspectiveLens()                    #普通的透视镜头
self.lens.setMinFov(50.534016)                   #设置短边的Field of View这时候如果宽高比是16:9的话长边搞好是80度,大地喜欢。
                                                 #因为有些时候窗体会被拉成高比宽要大的情况所以这里应该设置MinFov而不是默认的宽的FOV
self.lens.setAspectRatio(base.getAspectRatio())  #根据画面设置宽高比


#...其它的一些设置

self.accept('window-event', self._adjustAspectRatio)  #然后,要响应窗体大小改变的事件创建Panda3D的任务(说明文档里没有这个事件啊!好不容易才在panda3d的论坛里发现的说……)

#....嘛

用于响应事件的方法

def _adjustAspectRatio(self,arg):
    if self.camera:
        self.lens.setAspectRatio(base.getAspectRatio())  #动态改变宽高比

于是这样自定义camera就成功模仿了默认camera的窗体大小改变而不失真的效果了!XD

今天做Gal模式场景的管理 本来只想就像标准Gal一样做个2D场景与立绘的
然后一时兴起在透视Camera实现了……(嗯同时解决了上面的问题)嗯 于是就变成了表面是2D其实是3D(这不蛋疼吗!)
嘛,既然Panda3D是3D引擎那当然要有除了脑补中的3D战斗外更多地利用它的优点的地方
于是它变成了很容易混合2D和3D的界面的奇怪的东西了……
撒花!

tttt

嘛,另外不要问窝为什么在坑引擎……(望天,不如说第二阶段终于开始了吧

啊啊啊啊啊啊啊啊啊忘了德叔的坑了!!!!!!!!!!!!!!!!

python中用exec执行脚本命令的变量可访问性 (python3.3)

在python中写游戏引擎的时候经常会用到exec执行脚本命令和getattr动态调用函数
但是……使用exec执行脚本命令时,exec对外界变量的可访问性如何?外界对exec中的变量的可访问性又如何?

经过本大地一个简单的小测试后,大概结论如下
结论1:exec在最外层时后续的代码可以访问其中声明的变量,可以调用外部的函数
结论2:exec在最外层时在其中对变量进行的修改对外部有效
结论3:在函数中使用exec,对于简单的数据类型使用了值传递的方式,即exec中进行声名和修改对外部无效;但是全局变量的声明和修改是有效的;其定义的变量能被后面的exec访问但不能被本身的函数体访问
结论4:在类成员函数中exec可以定义、访问和修改类的成员;但是其中定义的普通变量只能被后面的exec访问(喵的好神奇!)
结论5:exec在最外层时后续的代码可以访问其中声明的函数和类

然后以下是测试过程

# -*- coding:utf-8 -*-
”’
Created on Jun 28, 2013
python中用exec执行脚本命令的变量可访问性的小测试 (python3.3)
@author: 大地无敌 – http://www.agrp.info
”’
 
#1、在最外层执行exec声明变量
exec (‘test = ‘miao” )
print (test ) #输出miao
 
#结论1:exec在最外层时后续的代码可以访问其中声明的变量,可以调用外部的函数
 
 
#2、普通修改和函数调用的测试
def plus( mm):
    return mm + ‘World!’
= ‘Hello ‘
exec (‘k = plus(k)’ )
print (k ) #输出Hello World!
 
#结论2:exec在最外层时在其中对变量进行的修改对外部有效
 
#3、在函数中使用exec
def main():
    test2 = 1
    exec (‘test2 = test2+233nabc=3nprint(test2)’ ) #输出的是234
    exec (‘print(test2)’ ) #输出的是1
    exec (‘global test3ntest3 = test2’ )
    exec (‘test4 = ‘How about this?” ) #输出How about this?
    exec (‘print(test4)’ )
    print (test2 ) #1而不是2,说明在函数中用exe没有改变函数中的变量
    print (test3 ) #输出的是1
    #print(test4) #会认为test4未定义
 
main ()
#print(test2) #会认为test2未定义,说明在函数中用exec访问的不是模块中的变量
print (test3 ) #输出的是1
 
#结论3:在函数中使用exec,对于简单的数据类型使用了值传递的方式,即exec中进行声名和修改对外部无效;但是全局变量的声明和修改是有效的;其定义的变量能被后面的exec访问但不能被本身的函数体访问
 
#4、类(构造)函数中的测试
class Test2:
    def __init__ (self ):
        exec ( “self.age = 20”)
        exec ( “abc = 65535”)
        exec ( “print(abc)”) #65535
        #print(abc)  #会认为abc未定义
 
test2 = Test2 ()
print (test2 .age ) #输出的是20
#print(abc) #会认为abc未定义
#exec(“print(abc)”) #会认为abc未定义
 
#结论4:在类成员函数中exec可以定义、访问和修改类的成员;但是其中定义的普通变量只能被后面的exec访问(喵的好神奇!)
 
#5、在exec中定义函数和类
exec (‘def test():n    print(‘hahahaha’)n’ )
test () #输出hahahaha
exec (‘class MyObject():n    def __init__(self):n        print(‘OKOK!’)n    def test(self):n        print(‘Hello’)’ )
myObject = MyObject () #OKOK
myObject .test () #Hello
 
#结论5:exec在最外层时后续的代码可以访问其中声明的函数和类
 
 
input (“nya!” )
”’
在会出现异常的代码都注释掉后的最终输出如下:
miao
Hello World!
234
1
How about this?
1
1
1
65535
20
hahahaha
OKOK!
Hello
nya!
”’

 

注意 在Python2.7 中 结果是

miao
Hello World!
234
234
How about this?
234
234
234
65535
20
hahahaha
OKOK!
Hello
nya!

也就是说在函数中使用exec对简单变量进行的声明和修改在python2.7中会反映到外界

温蒂达利安

温蒂达利安

ウィンディーダリアン | 大地無敵 [pixiv] http://www.pixiv.net/member_illust.php?mode=medium&illust_id=36589663

温蒂达利安。
手持大剑的守序邪恶面向对象幻术师“黑色温蒂”,妄想的饕餮。
以“大地无敌”为代号,进行各种奇怪的计划。
虽然奇怪的计划大概在有条不紊地进行中吧,
还是因为拖延症的原因才是得它们看上去是有条不紊地进行中的?

于是这个图顺便作为温蒂酱搬宿舍的纪念物好了……

再见沙河

这只是一个城市的一个高校到了某个年级要搬迁校区的学长的常见心境而已。——突然发现还有大半个月就要和这个地方说再见了。刚好某形式与政策课的论文也快到截止期限了,于是借着这样的风说说感想吧。

首先想到的大概是那个社团。某燃君在社团内部共享了一个告别沙河的自制文字冒险游戏,到现在只觉得是昨天的事情而已——其实那已经是一年前了。而我也将追随某燃脚步去。虽然好不容易建立起来的一些东西会成为回忆,不过有了回忆的羁绊大概才会更棒。再说这个社团,本来就是基本每个学期只需要见面一次的在线类型社团不是吗?即使人没有在一起,大家也能够像往常一样的一起努力不是吗?——本来想说这样就能满足了,其实一想还是完全不够啊!

123于是这个是去年某燃的随笔游戏

沙河真的是个很好的地方,除了一些课程和要求不尽人意之外,真是一个世外桃源。至少风景算是上品。只要有学生卡在手,就可以一个学期不出校门。食堂三楼的翔锅还没吃够,二楼的肥牛饭和鸡排饭比一楼更引人回味,而一楼早上的煎饼真是百吃不厌,油条也是最近才发现……我究竟是从什么时候开始喜欢上一个学校的食堂的饭菜?——你们要是想在食堂三楼的香锅场上战个痛记得叫上我啊!我会乘着4点半的校车赶来!

刚刚从物理实验室出来。这大概就是最后了。——两年沙河,一年物理,一年物理实验。本来以为再也不用做实验了是一件很令人愉快的事,但这种感觉是随着解放感而至的感伤吗?——说到遗憾的话也还有,毕竟我还没有在久负盛名的李老师的带领下做过实验。虽然在某种意义上大概明年能见到的可能性也存在吧……

还有一个伤心的地方是,再也不能见到野生的学妹!不过想想那群丧心病狂的助教,心里也就平衡了。嘛,这个话题还是不要展开比较好。不过,学长我只能帮到这里了。

或许某棵路旁的树下的铭牌还会留下我们存在过的印记。但是过不了多久,它也会换成新的铭牌吧。

宿舍。那边的宿舍,估计也不会有这边这样的感觉了——毕竟这是我第一次在名为“家”的地方意外开辟的据点——还有些连“家”也比不上的地方。住在这个宿舍的下一位会是什么样的人?在把最后一件物品打包之前,我会留下一张纸条什么的。因为我不是很在意细节问题,所以“留下这么多无法擦除的污渍真是对不起了。”大概会这样写道。——留下这么多无法擦除的回忆真是对不起了。

不过就算再怎么不舍,这一切也都会成为过去时。所以,让我们怀揣过去,迎接崭新的未来——

——你以为我会这样说吗?如果不是被迫的话,我还想在这个鸟不拉屎能够仰望星空的地方留上个三五年!翔锅还没战够,你以为这么简单就能把我轻易抹去?如果不是被逼的话我才不会想把我占据了两年的据点轻易地让给另一个人!虽然像是在说傻话一般,不能每天早上穿着拖鞋在名叫TD线的被早上的太阳晃瞎眼的生活怎么能接受!所以说——所以说!

我一定会回来的!

——虽然感觉做出了很不好的预言的样子。

 

456

最后附上一个半成品的做为留恋的半成品图吧。

嘛,虽然被拖延症所困,但是大地无敌和大家也不会就这样坑掉的哦。