想象一下,如果我们只需通过发一封邮件,电脑就会把屏幕截图、摄像头的画面回复给我;或者我发一句命令,电脑就会远程关机,或者启动某个程序。是不是很方便?Email My PC 就是这么一款非常简单实用的邮箱远程控制/监控 PC 的小工具,能让你在任何地方任何设备通过邮件轻松监视和控制电脑……
相比传统的 PC 远程控制软件,Email My PC 完全是另辟途径,彻底抛弃了图形化操作方式,只通过邮件即可与自己的电脑“沟通”进行远程控制或监视屏幕。
通过邮件远程控制电脑有几个好处,首先几乎在任何手机、电脑上无需安装客户端就能收发邮件,无需高速的网络、也不需消耗大量网络流量。虽然 Email My PC 目前能远程做的事比较有限,但它提供的功能对于很多人来说已经足够实用了,或者说,在某些特定的场景下,Email My PC 远远比传统的远程控制软件方便得多!
说了这么多,那么 Email My PC 通过邮件具体到底都能做些什么呢?从软件设置界面的「命令」标签中其实就已经能看出大概了。譬如给邮箱发送标题为 #shutdown 的邮件即可远程关机;发送 #screen 可以收到当前电脑的屏幕截图;发送 #cam 可以远程查看电脑摄像头的画面;发送标题 #button 并在正文中写上快捷键即可远程使用快捷键操纵电脑;而发送标题 #cmd 加上正文里写上具体的命令,即可实现执行各种系统命令或启动任意程序。
更多的介绍及最新版的下载请到官网查看。
[查看全文]
纯属兴趣爱好,让跟多的宅们了解什么是鱼儿~(纯手工打造,不喜勿喷)最好在虚拟机上实现,影子系统也行!!在此我用的是2003sever和Windows xp两台虚拟机。[查看全文]1.在本地主机win2003.解压其安装包,找到IIS解压包,拖入共享目录先打开虚拟机win2003sever,在虚拟机内找到控制面板,找到添加删选项,选择添加删除组件,《本地IP地址的查询方法:命令行,cmd,ipconfig!》2.如图:选择证书颁发机构最后查看是否安装成功。在主机的ie上写入192.168.64.128/certsrv申请证书后再在虚拟机进行证书颁发,颁发成功后进入虚拟机的计算机管理工具点网站,选择服务器证书,完成后在虚拟机c盘下看到此文件,在虚拟机内申请高级证书。将得到后的文件复制粘贴入上图中,得到后,再在虚拟机内将证书颁发然后进入页面再将该证书下下来,不安装,点击服务器证书,建立一个虚拟信道后,如果http:/不加s,如下图:无法访问,加s后,可以访问=================================================================================================建立钓鱼网站:在虚拟机内,先打开一个网页,www.baidu.com将文件另存为,将文件名改为baidu.htm在主机ie上输入http:/192.168.64.128/baidu.htm这样,简单的钓鱼网站制作成功,接下来通过监听软件来监听一下内部明文密文的实现,(工具:sniffer)http不加安全信道,通过sniffer,所得到的解码是以明文方式出现,如图:在虚拟机内通过ssl安全信道后(加s的情况):进入虚拟机后,点击属性,点击最下面的编辑,完成SSL信道加密。再进行监听:通过虚拟网卡,在虚拟机内通过ssl安全信道后(加s的情况):
接上一贴
所谓精灵动画,就是要让每一帧都动起来,这里我采用的是单帧的方式,利用pivotanimator来制作火柴人动画
做法请自行百度,导出单帧图片在一个目录然后利用photoshop结合成一张大图
这里我只做了部分,从上向下是向右走,向左走和待机状态(其实待机状态也分为面向左还是右)
最后,我们希望通过
if event.type == userevent.PERSONCHECKCHANGE:
p1.update(screen,p1state) #screen是屏幕对象,p1state是palyer1的状态
然后,每50ms触发一次userevent.PERSONCHECKCHANGE,来画下一帧
接下来,就需要仔细的思考一下这个person类要如何来做,才能满足只传入状态就能获得当前帧
要求:对于update函数传入‘left’,函数会在第一行循环圈定矩形,9帧
对于update函数传入‘right’,函数会在第二行循环圈定矩形,9帧
对于update函数传入‘right’,函数会在第二行循环圈定矩形,9帧
于是,我在class Person1类中做了如下定义,每个动作占一整行
item_dict=[
("left",personutils.child(w=256,h=256,itemlen=9)), #w和h是每帧的宽高
("right",personutils.child(w=256,h=256,itemlen=9)),
("normal",personutils.child(w=256,h=256,itemlen=9))
#可能会添加新的动作,比如'出拳',‘出脚’
]
child只是一个nametuple:child = collections.namedtuple('child','w h itemlen')
在init函数里加入一个init_child来加载我们的设定
def init_child(self):
dic = self.item_dict
nextindex = 0
for item in dic:
value = childRects(w=item[1].w,\
h=item[1].h,\
itemlen=item[1].itemlen,\
index=nextindex)
setattr(self,item[0],value)
nextindex = value.nextindex
分析一下:这段代码在运行时动态的向Person1类注入名称是left,right,normal的childRects类
childRects类如下:
class childRects(object):
def __init__(self,index,itemlen,h=256,w=256):
self.__h = h
self.__w = w
self.__itemlen = itemlen
self.init_rects(index,itemlen)
self.nextindex = index + h
def init_rects(self,index,itemlen):
change_mapper = lambda x,y: (x,y,x+self.__w,y+self.__h)
split_pos = range(0,\
self.__w*itemlen,\
self.__w)
self.rects = map(change_mapper,split_pos,\
[index]*itemlen)
def get_next_rect(self):
itor = [0]
def next_itor():
now = itor[0]
itor[0] = (itor[0] + 1) % self.__itemlen
return self.rects[now]
return next_itor
这一段对于C或者C++的同学可能有些难以理解,init_rects的作用就是在一行按照w和h画itemlen个方框,返回这些的列表
不得不说,python的lambda实在太过方便了
get_next_rect是一个闭包计数器,至于为什么是闭包,之所以选择闭包,额,等一下讲哈
类里面的nextindex是为了指向下一个动作的起始高度,比如left帧在0,0像素开始,那么right帧就会在0,256开始,也就是nametuple与构造函数差掉的那个index
至此,我们可以通过某个person1的实例p1,调用p1.right.get_next_rect来创建right帧的迭代器,这里的好处就体现出来了
def update_state(self,state):
bfstate = self.now_state
if cmp(state,self.now_state) != 0:
self.now_state = state
attr = getattr(self,self.now_state,"not found")
if type(attr)!=type(""):
self.next = attr.get_next_rect()
else:
self.now_state = bfstate
通过调用update_state并传入状态值,就会在实例中更新next方法,此时的next适配了各种状态
最后的最后,完成了update
def update(self,screen,state):
point = self.point
self.update_state(state)
n = self.next()
tmp = pygame.Surface((n[2]-n[0],n[3]-n[1]))
tmp.blit(self.image,(0,0),n)
attr = getattr(self,"action_"+self.now_state,"not found") #在处理动画的同时,我们还可以编写这个精灵的逻辑函数
if type(attr)!=type(""): #例如action_right
attr()
screen.blit(tmp,tuple(point))
逻辑函数在我的例子中比较简单,只有左移右移,因为normal态是不进行任何逻辑处理的233
def action_left(self):
point = self.point
point[0] -= self.speed
point[0] = max(0,point[0])
def action_right(self):
point = self.point
point[0] += self.speed
归根结底,程序完全是依赖注入的方式,这种设计下添加一个新的动作只需要设定 item_dict就可以动起来,添加action_名称就可以完成逻辑
这么一看代码复用度起始还是蛮高的呀
既然获得了各种状态,那么,状态之间的转换似乎就有必要讲一讲了
下节课,我们来讲讲FSM,传说中的状态机,嗯(深思状)
讲述比较乱,还是附上代码吧,运行game.py 就可以测试运行效果了,233
http://pan.baidu.com/s/1o6JtBse
[查看全文]
大家好,首先自我介绍一下,我叫小飞,是一名互联网公司的底层码农,从事着与游戏并不相关的职业。
所以,在制作游戏方面,我也是摸着石头过河,菜鸟一只。所以内容中有哪些错误,欢迎大家指出
本系列的目的是什么?
在我最开始学习游戏编程的时候,通常按照教程来学习引擎的使用方法,可是,
当一篇看完以后,我兴致勃勃的打算动手写一个游戏出来。。。却不知道怎样堆砌那些函数,能够正常的运作
好不容易乱七八糟拼凑了几屏代码,运行时改动一处,好好的demo变得面目全非
代码的耦合性太强,聚合度太低,毫无拓展性可言,健壮性更是无从谈起。
亲呀,这样的代码真的不是累赘吗?
有这样烦恼的童鞋们,这篇文章简直是为了你们量身定做的 2333
这个系列比起教学更像是一篇手记,面向的是对读完pygame教程后对使用方法有基本了解的童鞋们。
所以说,比起交给使用方法,我更倾向于记录下自己对于游戏框架的设计与思考。
那么,正片开始
========================================================================================
考虑格斗游戏的输入,大概如下
[上,下,左,右,轻拳,轻脚,重拳,重脚]
这是最基本的情况,事实上为了丰富游戏的可玩性,还会有各种手搓的招式
例如
[下下轻拳,左右左右轻拳]等等
前者,可以直接用event.get()对keydown事件进行监控
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
p1state = 'left'
if event.key == pygame.K_d:
p1state = 'right'
这里基本没什么可说的了,可是接下来,像下下轻拳这种东西,并不是一个键,而是一串指令,怎么办
首先,需要一个指令表,用于存储指令对应的状态
字典可以轻松的完成这个工作
CMDLIST = {
"ssj":"fight1",
"swj":"fight2",
"adadj":"fight3"
}
同时,还需要一个队列来 保存缓冲区输入的字符
cmdquery = ""
这个队列应该被send_charter(char)这个方法调用
def send_charter(char):
global cmdquery
cmdquery += char
for i in CMDLIST:
if cmdquery[0-len(i):] == i: #这里的操作,是只将缓冲区最后的序列与字典的key进行比较,成功则命中
return CMDLIST
return
这样的操作会带来二义性,例如key中包含了‘左右左右’与‘左右’解决办法就是设计指令的时候别包含子集呗
修改
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
p1state = 'left'
if event.key == pygame.K_d:
p1state = 'right'
result = command.controller.send_charter(chr(event.key)) #关于指令和队列,均被我分到了command.controller包里,归类
if not result:
p1state = result
ok,在考虑情况,如果我们输入的指令速度很慢,那么是不会触发这些招式的,所以
def clear():
global cmdquery
cmdquery = ""
在主循环前
pygame.time.set_timer(userevent.CLEARCOMMANDQUERY,1000)
userevent.CLEARCOMMANDQUERY是自己定义的事件,目的是为了触发清空缓冲区操作
最后:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
p1state = 'left'
if event.key == pygame.K_d:
p1state = 'right'
result = command.controller.send_charter(chr(event.key)) #关于指令和队列,均被我分到了command.controller包里,归类
if not result:
p1state = result
if event.type == userevent.CLEARCOMMANDQUERY:
command.controller.clear()
今天就先提到这里,下一篇我会结合代码提供一个拓展很方便的精灵动画类的实现,也就是player类
[查看全文]
作为一个技术宅的休闲活动就是研究一项非常冷门的技术,或者非主流奇葩的语言。首先,请允许我向大家介绍一下什么是BrainFuck,正如同它的名字一样,使用它和阅读它的代码就像是强♂奸你的大脑一样。下面我将用C语言为你展示如何实现BrainFuck语言解释器。
BrainFuck只有8条指令:
指令 | 含义 | 等价的C代码 |
> | 指针加一 | ++ptr; |
< | 指针减一 | --ptr; |
+ | 指针指向的字节的值加一 | ++*ptr; |
- | 指针指向的字节的值减一 | --*ptr; |
. | 输出指针指向的单元内容 | putchar(*ptr); |
, | 输入内容到指针指向的单元 | *ptr = getchar(); |
[ | 如果指针指向的单元值为零,向后跳转到对应的]指令的次一指令处 | while (*ptr) { |
] | 如果指针指向的单元值不为零,向前跳转到对应的[指令的次一指令处 | } |
#include <string.h>
#include <stdio.h>
#define TOKENS "><+-.,[]"
#define CODE_SEGMENT_SIZE 30000
#define STACK_SEGMENT_SIZE 1000
#define DATA_SEGMENT_SIZE 30000
typedef void (*Callback)(void);
struct {
char cs[CODE_SEGMENT_SIZE]; /* Code Segment */
long ip; /* Instruction Pointer */
char ss[STACK_SEGMENT_SIZE]; /* Stack Segment */
long sp; /* Stack Pointer */
char ds[DATA_SEGMENT_SIZE]; /* Data Segment */
long bp; /* Base Pointer */
Callback fn[128];
} vm;
void vm_forward() {
vm.bp = (vm.bp + 1) % DATA_SEGMENT_SIZE;
}
void vm_backward() {
vm.bp = (vm.bp + DATA_SEGMENT_SIZE - 1) % DATA_SEGMENT_SIZE;
}
void vm_increment() {
vm.ds[vm.bp]++;
}
void vm_decrement() {
vm.ds[vm.bp]--;
}
void vm_input() {
vm.ds[vm.bp] = getchar();
}
void vm_output() {
putchar(vm.ds[vm.bp]);
}
void vm_while_entry() {
if (vm.ds[vm.bp]) {
vm.ss[vm.sp] = vm.ip - 1;
vm.sp++;
} else {
int c = 1;
for (vm.ip++; vm.cs[vm.ip] && c; vm.ip++) {
if (vm.cs[vm.ip] == '[') {
c++;
} else if (vm.cs[vm.ip] == ']') {
c--;
}
}
}
}
void vm_while_exit() {
if (vm.ds[vm.bp]) {
vm.sp--;
vm.ip = vm.ss[vm.sp];
}
}
void setup() {
int c;
int i;
memset(&vm, 0, sizeof(vm));
vm.fn['>'] = vm_forward;
vm.fn['<'] = vm_backward;
vm.fn['+'] = vm_increment;
vm.fn['-'] = vm_decrement;
vm.fn['.'] = vm_output;
vm.fn[','] = vm_input;
vm.fn['['] = vm_while_entry;
vm.fn[']'] = vm_while_exit;
for (i = 0; (c = getchar()) != EOF;) {
if (strchr(TOKENS, c)) {
vm.cs = c;
i++;
}
}
}
void run() {
while (vm.cs[vm.ip]) {
vm.fn[vm.cs[vm.ip]]();
vm.ip++;
}
}
int main(int argc, char* argv[]) {
if (argc > 1) {
freopen(argv[1], "r", stdin);
}
setup();
run();
return 0;
}
[/mw_shl_code]
下面我们来看看它的Hellow World程序:
[mw_shl_code=c,true]brainfuc$ cat helloword.bf
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.
brainfuc$ ./bf helloword.bf
Hello World!
brainfuc$[/mw_shl_code]
[查看全文]本帖最后由 ntyt123 于 2015-5-27 17:58 编辑
[查看全文]本教程面向:觉得编程高大上想学却又望而却步的地球人不想学编程可是又对编程有一丝好奇的地球人对所有事务好奇的地球人本教程禁止汪星人打开!哼!还有,Milky是我家的蠢喵~~~~~语言的高级与低级编程语言的种类有很多,像C++、Java、PHP、C#、Python等等,这些被称之为高级语言。一般程序员使用的都是高级语言,与高级语言区别开来的低级语言包括机器语言和汇编语言。机器语言就是写出一大串的”0“和”1“让电脑进行相应的操作,可是一大串的”0“和”1“对愚蠢的人类来说实在太难理解了,于是人们想到了另外一种语言,即所谓的汇编语言,汇编语言比机器语言稍微好理解那么一点点点,比如用”ADD“来表示加,用”MOV“来表示传递数据等等,计算机再将这些命令翻译成机器语言开始运行,所以运行效率会比机器语言慢一点点。大概的汇编语句是这样的:D1 DD 12345678HD2 DD 9ABCDEF0HD3 DD ?┆MOV DX,D1MOV AX,D1+2MOV BX,D2MOV CX,D2+2ADD AX,CXADC DX,BXMOV D3,AXMOV D3+2,DX这段汇编的意思是把求出的D1与D2的和存到D3中去。…………呵呵…………拜托我只是想耍个帅,你这样我还怎么装逼啊!相应的换成高级语言:C#:Int D1=1;Int D2=1;Int D3=D1+D2;Python:D1=1D2=1D3=D1+D2是不是通俗易懂?而且汇编语言的一大弊端是,它跟计算机的硬件联系紧密,同样一段代码,放到另外一台计算机上可能就运行不了了。当然,汇编语言现在并没有淘汰,它的运行效率比高级语言写出来的程序要高,而且特别在软件破解等方面有着天生的优势。对于普通的程序员来说,学习和使用汇编语言会很痛苦,于是高级语言出现了。高级语言相对于初级语言来说,更符合人类的阅读、书写习惯,当然做到这一步也是有代价的,计算机是看不懂高级语言的,所以要先将高级语言翻译成机器语言,并且这一过程比汇编语言翻译成机器语言要慢,但是架不住高级语言好学好用好装X。选个好吃的语言言归正传,C#也是高级语言的一种,是微软在2000年推出的。相对于动辄几十年历史的其他语言来说,C#绝对是个青春无敌的美少年。C#读作CSharp,最开始他的名字叫COOL。相对于其他高级语言,C#几乎包含了当今软件研究的全部成果:面向对象、反射、类型安全、组件技术、自动内存管理、跨平台异常处理、版本控制、代码安全管理……C#的语法与C++大部分相同或类似,而且使用起来更简单,开发周期更短。借助MONO等技术可是进行跨平台开发。当然,C#也有缺点,比如写出来的程序必须在.NET运行库的基础上运行,简而言之就是需要在电脑上装上.NET FrameWork系列软件,经常玩游戏的对这个应该不太陌生。吃饭前先选个筷子通常用来开发软件的应用程序被称为:Integrated Development Environment(缩写IDE),即集成开发环境。是不是有点晕?其实就是写代码并将代码变成可以运行的程序的小软件。那C#的IDE有哪些呢?1:Visual Studio:超级宇宙无敌最好用的IDE,没!有!之!一!用后绝对会上瘾。C#的娘家微软出品,强大的代码提示和调试功能,IDE其实只是他的功能之一,另外还提供了UML工具、代码管控工具、SQL工具、团队开发等各种各样高大上的功能,当然,这些功能对于只想常常编程是个什么味道的地球人来说可能一辈子都用不上。对于新手,VS最好用的莫过于代码提示了,如果再装上ReSharper插件简直灭天灭地,这个等后面接触到再细说。收费,但是有破解。2:MonoDevelop:支持跨平台,这点之前的VS没有,不过最新的VS2015开始支持安卓开发了。第一次接触到这货是因为学习Unity3D,Unity3D自带mono。免费。3:SharpDevelop:体积小,10M左右(VS 2GB+),相应的功能就少了很多,但对于熟练的程序员来说足够用。我没有用过,所以不做评价。免费。以后的教程中,将使用VS这双镶玉镂金大长筷子。编程对于非程序员来说有没有用呢?举个例子,小明每天都要花两个小时的时间整理Excel表格,如果他会编程的话,花两天时间写个程序出来,以后每天他只需要花两分钟来整理Excel表格。爽不爽?至于你愿不愿意花两天时间来写程序,就看你自己了。编程可以干哪些炫酷的事情?自己写个网站!没有想玩的游戏?自己写一个吧!想装个闹钟课程表之类的小软件又怕网上随便下载的有病毒木马?自己写一个吧!P站看到一堆喜欢的图片可是一次一次右键保存太麻烦?写个爬虫自动抓取吧!(这个我会出专门的教程)嫌QQ广告多?自己写一个发给女神,两个人的私密聊天软件!……嘛,教程一貌似快结束了,可是我好像什么有用的都没说?!留到下一期吧。Milky都能学会的C#编程(二)——C#程序的初体验顺便宣传一下自己的个人博客”www.kingroy.net“,由于刚刚搭建完毕所以还没有什么干货。这节课听明白了吗,Milky?喵~
本帖最后由 黑影 于 2015-5-10 15:09 编辑
这个题目我在网上看到有好多种做法,我自己也想出了一种做法。[mw_shl_code=java,true]import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/*
* 思路:
* 1.定义三张表,存储中文数字和货币单位。
* 2.键盘录入使用IO流的BufferedReader进行接收键盘录入。
* 3.把录入的阿拉伯数字弄成字符数组,如果有小数位就先分割成整数位和小数位。
* 4.先处理整数位再处理小数位,把每个数字所在位置的角标对着中文数字的表进行转换,
* 转换完后再从对应的位置插入货币单位。
* 5.把格式进行修正匹配后打印输出。
*/
public class MoneyConvert {
//创建中文大写数字的表和货币单位的表
static String[] cnNumTab = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒","捌", "玖"};
static String[] integerUnitTab = {"", "拾", "佰", "仟", "万", "拾", "佰", "仟", "亿", "拾", "佰", "仟"};
static String[] decimalUnitTab = {"角", "分", "厘"};
public static void main(String[] args) {
System.out.println("请输入金额:");
//创建流对象,用于接收键盘录入的数据
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
try {
//把键盘接收的金额数据的小数位和整数位分隔开
String str = in.readLine();
String[] strArr = str.split("\\.");
//把分隔好的数位金额数据分别打散成字符数组
char[] chNumArrInteger = strArr[0].toCharArray();
//把阿拉伯数字转换为中文的大写数字
String[] convertIntegerNum = convertUpper(chNumArrInteger);
//定义合拼数字和单位用的容器
StringBuilder container = new StringBuilder("圆整");
//嵌入货币单位到转换好的中文大写数字里去
for(int x = convertIntegerNum.length -1, y = 0; x >=0; x--, y++) {
String num = convertIntegerNum[x];
if(num.equals("零")) {
//判断数位是否是仟万亿的位置,是则插入单位
if(y == 4 || y == 8)
container.insert(0, num+integerUnitTab[y]);
else
container.insert(0, num);
} else {
container.insert(0, num+integerUnitTab[y]);
}
}
//如果有小数位,则对小数位的数也进行同样的转换操作
if(strArr.length == 2) {
int len = container.length();
container.replace(len - 2, len, "圆");
char[] chNumArrDecimal = strArr[1].toCharArray();
String[] convertDecimalNum = convertUpper(chNumArrDecimal);
//嵌入货币单位到转换好的中文大写数字里去
for (int x = 0; x < convertDecimalNum.length; x++) {
container.append(convertDecimalNum[x]+decimalUnitTab[x]);
}
}
//格式修正
String put = container.toString();
put = put.replaceAll("佰零+万", "佰万");
put = put.replaceAll("佰零+亿", "佰亿");
put = put.replaceAll("仟零+万", "仟万");
put = put.replaceAll("仟零+亿", "仟亿");
put = put.replaceAll("零+", "零");
put = put.replaceAll("零万", "万");
put = put.replaceAll("零万零", "零");
put = put.replaceAll("拾零", "拾");
put = put.replaceAll("零圆", "圆");
//完成后打印输出
System.out.println("该金额的大写形式为:"+put);
} catch (NumberFormatException e) {
System.out.println("输入错误,请输入有效的金额数字");
} catch (IOException e) {
e.printStackTrace();
}
//键盘录入接收完数据后流会自然断开了,无需调用关流资源的方法了
}
//把阿拉伯数字转换为中文的大写数字
public static String[] convertUpper(char[] arr) {
String[] convertNum = new String[arr.length];
for(int x = 0; x < arr.length; x++) {
int num = Integer.parseInt(arr[x]+"");
convertNum[x] = cnNumTab[num];
}
return convertNum;
}
}
[/mw_shl_code]
方法貌似有些麻烦,还在学习中,写得可能不太好。
[查看全文]