分类目录归档:技术

一个游戏运营项目失败的思考

这是我对自己参与的一个项目失败的思考,有点马后炮的赶脚。仅仅代表个人的观点和看法,不一定正确,仅供记录我这个阶段的一些想法,积累下来以供将来重新的审视与提高。

先简要的介绍一下这个项目,这是一个网络游戏在海外运营的项目,促成这个项目的开始是出自同事以往行业内的从业经历,恰逢其会的是该同事具有前期能引流的人脉并且也愿意一番尝试,在技术上也具有在预期时间内完成基础平台建设的能力。在项目启动之初,可谓「天时、地利、人和」齐活了,一个比较完美的开始就这样诞生了,剩下的就是甩开膀子,在快速迭代试错中迈着小碎步向前奔跑,以成就一番事业。

「愿望总是美好的,现实总是残酷的」,我甚至不知道这个项目最终结束的具体时间,因为项目进行的中间我就已经离开这个游戏创业项目了,很短暂的开始,很短暂的结束,但当整个团队决定开始增加新方向的时候,这个项目终将结束在我看来也是必然的。

gameplatform

按照这个项目来说,项目的主体共有三方组成:游戏厂商、初始用户导入方、平台运营团队。三方各司其职,共同推进整个项目的发展。

(1)被选中且能够与我们开展合作的游戏厂商的主要工作是完成游戏的接入,游戏的升级维护及节日活动的推出与定制,另外就是三方的结算对账。
(2)初始用户导入方完成用户的引流工作,以及运营分成的财务结算对账,完成境外其他资源引流的合作洽谈,找出最佳的引流途径。
(3)平台运营团队就是我们了,主要负责运营平台的建设、游戏的筛选与签订合同、游戏接口与平台的接入、平台的充值及换算、后台数据分析与核对、游戏运营活动的策划与运营推广、游戏客服、「建立自己的用户资源」、与各方财务结算。

游戏厂商在整个进程中的配合是非常良好的,在发生问题的时候总是能及时得到反馈,在活动及游戏内资源的支持上也不遗余力,而且从洽谈的过程中,能明显的感觉到他们是乐意合作的。

初始用户的引流工作虽然是资源方乐意尝试的,但不是其主营,这点上可能力度有待进一步加强,这些可以通过沟通来解决,还有就是对于引流的效果应该由我们结合引流方式给予资源方一定的支持,当然这些是要依据一定的数据方式,比如在游戏中做一些有奖励的调查问卷来获得其大部分的来源途径,其实这些在资源方那边是可以统计出来的。

我主要负责技术这块,并且参与跟游戏厂商的洽谈接触,在初始系统基础上安排设计人员和开发人员进一步定制以后基本上满足开始的运营需求,整个平台就这样开始运营了。我一直认为在一件事开始之后,专注与围绕专注开展工作是一个前提,就这个平台开始运营之初,构成其未来的主要工作集中在两部分:「其一是运营推广,这是重中之重,其长期努力的方向是建立自己的用户资源;其二是围绕运营推广提供强劲持久的技术驱动力,持续发展运营平台及其周边增值服务,保证给不同类别的用户持续输出富有娱乐性的游戏」。

围绕这两部分开展工作就是基础,刚开始运营其实从数据上来看还是比较符合预期的,在差不多一个月单游戏单区的情况下,用户注册数、每日在线数、充值数、日注册及活跃增长数及用户留存率上来看还相对符合预期,下面是一个月的部分充值记录。

paysummary

有了一个好的开始,但随后突然就放下了,主要的工作没有行之有效的开展,或者说没有足够的努力。危机意识不强,对技术长期驱动力的价值也不太认可,加上团队成员的实际生活问题等诸多因素的影响下,又有了开展其他行业新业务想法。在这种情况下,我最终选择了离开,因为我没有更多的资金投入开展新的业务,同时我也不认为当时的团队与投入能够有精力同时开展两条线的业务。

至于说主要的工作没有行之有效的开展是我个人的观点,对于我这个初次涉足游戏行业的人来说,在开始到离开这段时间其实有不少的想法,比如说在通过资源方引流的原始用户基础上,通过怎样的策划与推广,带来新的朋友用户,能不能制订积分体系加物质激励来完成?能不能通过游戏虚拟物品激励来完成,平台自己是否增加用户推荐体系并给予满足条件的推荐用户以激励?围绕游戏如何建立社区论坛?能否增加周边商城拓展游戏增值服务?满足这些运营平台应怎样重新架构? 诸如此类的想法有不少,但是这些想法没有成文后与团队成员进行充分的沟通,虽然这些想法对于初涉游戏行业的我显得比较稚嫩,但至少也应该跟团队成员讨论一下,在讨论过后相信自己也能获得长足的提高,增加对这个行业的认知。

危机意识不强的很大一部分原因是被这开始的充值额冲昏了头脑,按照一款游戏一个区来计算,想来多款游戏多个区就能达到预期,从我后来离开后的间断性关注中,先后上线了新的两款游戏,并且增加了新开区,但是充值及用户增长却一度中断,中间我没有看到任何针对这些不好影响的调整。这段时间我的猜测是人力资源不能跟进以保证用户的使用引导及足够的支持工作,由于新开展的其他行业新项目占据太多的精力,导致迟迟没有建立初步的用户服务机制、用户引入机制、用户激励机制、用户参与机制等。且在整个行业的发展中,游戏的变化也是急剧的,缺少对端游、页游、手游这些不同类型游戏的持续性关注。

再往后就没有往后了,却留下了诸多的不良影响,影响之一是在合作过程中给其他两方留下了一定的印象;影响之二是给玩过一阵的玩家留下了一定的印象,进而导致资源方也给玩家留下了足够的印象;影响之三是给所有团队成员留下来一定的印象。那么收获呢?

对于我来说这个短暂的创业经历有几点收获:

(1)要一直专注,所有要做的事情都要围绕最初设定的目标来做,尝试能够尝试的一切方法只为向目标迈进或者由目标衍生的新目标,直至结束,在未终止前我们其实没有更多的精力同时专注两件事;
(2)要有危机感,要给自己设定尽量涵盖全范围的最差的情况,然后设法找到解决方式,时刻保持危机感能促使专注;
(3)运营是重中之重,运营始终需要强力的技术作为保障,从这个角度来讲,技术是运营的支撑,技术是驱动力,要尽量获得团队成员对技术的认可,运营平台系统的建设不是一锤子买卖,需要长时间的演变,从功能到架构;
(4)要设定退场时对各方影响的补偿机制,用户从开始使用提供服务的第一天就会投入情感,任何时候不要让用户失望,说不定结束前小小的沟通就能超出用户的预期;
(5)人在任何时候都是关键,保持足够的沟通能够增加互相的了解,比较理想的是在没明确结束前,大家都能全力的参与其中;
(6)多少人做多少事,我们往往太过相信自己能够做的更多,可往往我们并不能做更多的事情,我们往往过高估计自己。

php中的魔术方法

php中内置了不少被赋予魔术性质的「魔术方法」,魔术方法以双下划线开头「__」,在类中使用,在特定的条件下自动在程序中被调用,由于具有在特定条件下自动被调用的特性,使得编程过程得以简化。

在PHP中魔术方法有:__construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __toString(), __invoke(), __set_state(), __clone(), __autoload()

1. __construct() 和 __destruct()

__construct()和__destruct()分别称为构造函数与析构函数,在对象被创建和销毁的时候由系统自动调用,跟其他编程语言中构造函数与析构函数一样,也是在面向对象编程中使用最频繁的。

构造函数主要完成对象在创建时候的初始化工作,一般用于初始化对象的成员,在PHP中,子类使用父类的构造函数必须使用parent::__construct()显示调用,不支持隐式自动调用。

对应的析构函数是对象在被系统销毁时自动调用。包括对象被显式销毁或者该对象的所用引用都被删除。跟构造函数一样,子类析构函数使用父类析构函数同样使用parent::__destruct()显示调用。

construct

2. __call()和__callStatic()

当调用对象不可访问的方法或者没有的方法时自动调用__call()魔术方法。该魔术方法有两个参数,第一个是调用的方法名称,第二个参数是枚举数组参数列表。用静态方式调用不可访问的方法或者没有的方法时自动调用__callStatic()魔术方法。

测试后发现对于存在但不可访问的方法并不能通过__call来调用,调用顺序为,先在自己类中寻找方法,如没找到,向父类中寻找,如果在父类中找到则调用父类中方法,如果没有找到而本类中有__call方法则执行__call魔术方法。

call_01

该魔术方法另外一个比较重要的用途就是实现重载,在PHP手册中这两个魔术方法介绍的标题也是方法重载。

call_02

3. __get() 和 __set()

当读取不可访问或者未定义的属性时,访问__get()方法。当设置不可访问或者未定义的属性时,访问__set()方法。

4. __isset()和__unset()

当在一个未定义或者不可访问的属性中调用isset()函数时访问__isset()方法。当在一个未定义或者不可访问的属性中调用unset()函数时访问__unset()方法。

 5. __sleep()和__wakeup()

这两个魔术方法在进行序列化的时候使用,通过序列化可以将任何类型数据转化为字符串格式,我们可以通过序列化对象,将其转化为字符串格式保存起来。在进行序列化的时候,检查类中是否有__sleep()魔术方法,如果有就调用该方法。在进行反序列化的时候会检查类中是否有__wakeup()魔术方法,如果有就调用该方法。

通常在__sleep()方法中处理不需要序列化的部分内容或者做一些对象的清理工作,而在__wakeup()方法中进行一些初始化操作。这两个方法是配合序列化和反序列化使用的。

6. __toString()

将对象当初字符串在程序中使用时,会自动调用该方法,例如我们echo一个对象时将调用这个方法,如果不存在该方法,则出现错误。

7. __invoke()

当尝试以调用函数的方式调用一个对象时,__invoke 方法会被自动调用。

8. __set_state()

当调用var_export()导出类时,该方法被自动调用。

9. __clone()

复制对象时使用clone方法,在复制完成时,如果定义了__clone方法,则会自动被调用,可用于修改新复制对象的属性或进行初始化工作。

10. __autoload()

使用这个方法可以进行类的自动加载,比如我们可以在该方法中完成包含文件的自动加载。

autoload

mysqli中多语句查询insert_id和affected_rows

在php的mysqli中有多条SQL语句执行的函数multi_query,可以一次执行多条SQL语句,对于不返回结果集的SQL语句在使用中发现获取insert_id和affected_rows不能自动进行多语句的累加数据,还得配合more_results「是否还有结果集」和next_result「下一个结果集」来进行计算,按照预计的来讲对于不返回结果集的SQL语句来说,应该能直接返回最后插入的ID和受影响的行数,结果却不然,在此记录一下。

<!--?php
/*
 *  使用mysqli的多语句查询multi_query中获得最后插入ID和受影响的行数
 *  数据库表为shops,字段有id,name,price,nums,desc,id为子增长字段
 */
header('Content-Type: text/html; charset=utf-8');

$mysqli = new mysqli("localhost", "root", "liutao", "test");

if($mysqli--->connect_error) {
  echo '错误:' . $mysqli-&gt;connect_error;
  exit;
}

$sqls = "insert into shops(name,price,nums,desc) 
  values('笔记本','1.2','1000','B5 笔记本');
insert into shops(name,price,nums,desc) 
  values('0.5中性笔','1.8','30','0.5的黑色中性笔');
insert into shops(name,price,nums,desc) 
  values('档案袋','2.2','100','A4透明塑料档案袋');
insert into shops(name,price,nums,desc) 
  values('订书钉','3.5','50','订书钉');";

if($mysqli-&gt;multi_query($sqls)) {
  $affectRows = 1; 
  do {
    $affectRows += $mysqli-&gt;affected_rows;
    $mysqli-&gt;next_result();
  } while($mysqli-&gt;more_results());
  echo "执行成功!<br> 最后插入的id:{$mysqli-&gt;insert_id} <br> ";
  echo "共影响的行数:{$affectRows} <br>";
} else {
  echo '错误:' . $mysqli-&gt;errno . '(' . $mysqli-&gt;error . ')';
}

$mysqli-&gt;close();

?&gt;

执行结果:

mutiquery_id_affectedrows

常见的腻子脚本功能摘要

经常见到一些网站中用一些腻子脚本「polyfill」,对其主要的功能进行一下摘要记录。

html5shiv.js  让IE8及更低版本的IE浏览器识别section、article、nav等HTML5元素;
selectivizr 让IE6/7/8 支持:first-child 等CSS选择符;
CSS3Pie 让低版本的IE支持圆角、渐变、边框图片、阴影等可视化CSS3功能;
Respond.js 让旧浏览器支持媒体查询;
-prefix-free 为需要厂商前缀的CSS3声明增加前缀;
borderBoxModel.js 让IE6/7支持CSS3的box-sizing属性;

这些腻子脚本主要用于弥补IE及低版本浏览器的不足,在GitHub有一个腻子脚本列表,参见「这里」。

php学习练习(1)-简单的日历类

追溯到我专职写程序的日子已经是若干年以前了,依稀记得从08年后半年开始,就没有在工作中专职全力写程序了,偶尔写点也是基于验证性的东西。当然不把写程序当作职业中的一部分是有很多借口,但都是借口,虽然年龄已经不小了,但是重新捡起来还是可以的,最近恰逢想要写一个系统,于是开始动手。

有「归零」的心态加上持续的练习是必不可少的,提高写程序的水平唯一方法就是不断的进行编码练习。当然练习是基于获取知识后的实践,再结合项目实际应用,积累一段时间后,自然会重新站起,在自己的博客上记录一下这段时间,今天从一个简单日历类开始。

实现基本的日历类Calendar功能,类向外公开一个display方法用于显示日历,能够按照月、年显示日历信息,简单日历类主要练习PHP的一部分日期时间函数,基于功能,类图如下:

calendar

display方法用于显示日历
weekList方法用于列出日历中的星期
daysList方法用于列出每个月的天数
editDate方法用于改变日历显示
构造方法完成对成员的初始化

类文件名为:calendar.class.php ,测试文件为:test.php ,具体代码如下:

year = isset($_GET['year']) ? $_GET['year'] : date('Y');
    $this->month = isset($_GET['month']) ? $_GET['month'] : date('m');
    $this->daysOfMonth = date('t', mktime(0, 0, 0, $this->month, 1, $this->year));
    $this->dayOfWeek = date('w', mktime(0, 0, 0, $this->month, 1, $this->year));
  }

  function display() {
    echo '';
    $this->editDate();
    $this->weekList();
    $this->daysList();
    echo '
} private function weekList() { $week = array('日','一','二','三','四','五','六'); echo ''; for($i = 0; $i < count($week); $i++) { echo ''. $week[$i] .''; } echo ''; } private function daysList() { echo ''; for($col = 0; $col < $this->dayOfWeek; $col++) echo ' '; for($day = 1; $day <= $this->daysOfMonth; $day++) { $col++; if($day == date('d')) { echo ''. $day .' } else { echo ''. $day .''; } if($col % 7 == 0) { echo ''; } } echo ''; } private function editDate() { echo ''; echo '<<'; echo '<'; echo ''. $this->year . '年'. $this->month .'月'; echo '>'; echo '>>'; echo ''; } private function prevYear($year, $month) { $year--; if($year == 1970) { $year = 1970; } return 'year=' . $year . '&month=' . $month; } private function prevMonth($year, $month) { $month--; if($month<1) { $month = 12; $year--; } return 'year=' . $year . '&month=' . $month; } private function nextMonth($year, $month) { $month++; if($month > 12) { $month = 1; $year++; } return 'year=' . $year . '&month=' . $month; } private function nextYear($year, $month) { $year++; return 'year=' . $year . '&month=' . $month; } } ?>

测试文件test.php,代码如下:

display();
?>

测试结果:
calendar.test

到这里就完成了这个简单的日历类,当然该类是仅仅用于展示日历的一个练习,如果用于实际则需要进一步改进,有几个方面可进一步改进:

1. 日历类一般用于前端,用javascript实现日历类在实际项目中应用应该好于用php这个服务器的脚本语言实现;
2. 如用php则应该非本练习中这样整页面向服务器提交请求,而应该使用AJAX就该日历部分展示与服务器进行异步数据传输;
3. 就功能上可增加输入年跟月来获取日历的方式;
4. 就展现上可采用模板,并用层叠样式表来设定样式;

–EOF–