punya代码分析跟学习笔记

punya代码分析和学习笔记

punya(DXプニャリン競争)是用DxRuby实现的一个小游戏。

see also: 

http://www20.atpages.jp/papihime/

http://www20.atpages.jp/papihime/ruby/index.htm

下面是我的学习笔记。

 

一、场景模块(DXRuby的场景框架):

 

1. 类

(1) Scene::Exit

退出场景类,空类,表示场景为空(见Scene.main_loop)

(2) Scene::Base

抽象类,Scene.main_loop的第一参数

 

2. 方法

(1) Scene::Base#initialize

构造函数。清空下一场景;帧数设为0;调用init。

(2) Scene::Base#__update

帧数加一,调用update。

(3) Scene::Base#init

抽象方法。初始化事件。

(4) Scene::Base#quit

抽象方法。退出场景并且将要进入下一个场景时的事件。

(5) Scene::Base#update

抽象方法。逻辑更新或场景切换事件。

(6) Scene::Base#render

抽象方法。界面渲染事件,发生在update后。

(7) Scene.main_loop(scene_class, fps = 60, step = 1)

静态方法。

* scene_class是Scene的子类,这里的作用相当于模板参数(实际是传入类构造器);

* fps是窗口最初的指定帧率。

* step是默认fps倍数(在运行期间可按PGUP和PGDN键调节),表示在一个循环内执行多少次渲染和逻辑更新。当它放大时窗口的fps随之缩小,使每秒执行的次数保持相同。

作用:

1) 构造出最开始的scene

2) 按PGUP和PGDN键调节更新内循环数。

3) 调用Scene.Base的回调方法

4) 判断scene.next_scene,如果非空的话构造新的scene读写。

5) 按ESCAPE键退出窗口循环

3. 属性:

(1) Scene::Base#next_scene

可读写。Scene.Base类的子类的类构造器。等于Scene.Exit的话退出。

(2) Scene::Base#frame_counter

只读。从最开始到目前为止的update次数,在update前加一。用于实现场景的透明度和闪烁动画。

4. 出现过的DxRuby API

* Window.loop

窗口循环

* Window.fps

设置窗口帧率

* Input.keyPush?

键盘当前是否按下状态?

 

二、dx_punya模块(游戏实现)

1. 类

(1) LogoStart

logo,Scene::Base的子类

(2) TitleScene

标题,Scene::Base的子类

(3) MenuScene

菜单,Scene::Base的子类

(4) CharactersScene

帮助与说明,Scene::Base的子类

(5) Punya

每个角色实例的设置

(6) PunyaRaceScene

游戏主界面。

 

2. 主入口

Scene.main_loop LogoStart

从LogoStart场景开始进入Scene框架主循环

 

3. 各个类的方法和字段

* LogoStart#FADE_IN_TIME:动画总时间

* LogoStart#init

* LogoStart#go_next_scene

* LogoStart#update

* LogoStart#render

1) 把frame_counter作为定时器参照修改images/logo2.png的显示透明度(渐现后渐隐)

2) 到达FADE_IN_TIME时间后转至下一个场景TitleScene

* TitleScene#init

* TitleScene#go_next_scene

* TitleScene#update

* TitleScene#render

1) 把frame_counter作为定时器参照修改背景图images/bg_title.png的显示透明度(渐现)

2) 提示文字images/press_any_key.png闪烁显示(某些时候不显示)

* MenuScene#init

* MenuScene#go_next_scene

* MenuScene#update

* MenuScene#hit_img?(img):鼠标当前位置是否落在某个菜单图片上。

* MenuScene#render

1) 背景由30个images/menu_tile.png砖块数组组成

2) 标题文字为images/menu_title.png

3) 菜单图片(选择)为images/menu#{i}.png,共三个

4) 菜单图片(未选择)为images/menu#{i}_back.png,共三个

5) 菜单(选择,未选择)信息数组有三个条目:

选择数组(img[])条目为[x坐标, y坐标, 菜单图片,是否当前选择]

未选择数组(img_back[])条目为[x坐标, y坐标, 菜单图片]

6) 按空格或鼠标左键时跳转场景。

根据@cursol_id的值选择跳转到:

PunyaRaceScene,CharactersScene,TitleScene

7) 根据鼠标当前所在位置判断选择哪个菜单

是否落在菜单数组条目,

根据img[0],img[1],image[2].width,image[2].height来判断。

8) 分别绘画

@bg_tiles:循环平铺,根据frame_counter进行偏移(不超过e.width)

形成倾斜方向的运动动画。

@back_menus:循环3次绘画。

@menus:如果@menus[i][3]为1时才绘画。

@title:绘画标题。

* CharactersScene#init

* CharactersScene#go_next_scene

* CharactersScene#update

* CharactersScene#render

1) 渐现背景图images/bg_characters.png(alpha随frame_counter而增加)

2) 空格或鼠标左键跳转到下一个场景MenuScene

* Punya#initialize(idx)

* Punya#update(frame_counter):由PunyaRaceScene场景类的update方法调用

* Punya#goal?:此精灵角色是否到达终点

* Punya#render:由PunyaRaceScene场景类的render方法调用

1) 构造函数传入角色编号idx

加载images/punya#{idx}.png的6张子图片(3*2)(动画精灵图片)。

根据idx算出@x, @y

@move为0,指示@image数组的下标(动画精灵的当前帧数)

2) 根据@x和@y绘画图片@image[@move]

3) 根据frame_counter,在合适的时候增加@i。

4) 根据@i切换精灵的帧图片:

到达终点:@move修改为3->4->5->4->...

未到达终点:@move修改为0->1->2->0->...

5) 根据@i移动精灵

到达终点:不动

未到达终点:@x += rand(4)

6) 精灵的@x超过560时认为到达终点

* PunyaRaceScene#init

* PunyaRaceScene#go_next_scene

* PunyaRaceScene#update

* PunyaRaceScene#render

1) 绘画背景图images/bg_race.png

2) 创建6个Punya精灵

3) 调用精灵的update和render方法

4) 空格或左键跳转到下一个场景MenuScene

 

4. 出现过的DxRuby API

* Image.load

加载图片

* Input.keyPush?

判断键盘是否按下

* Input.mousePush?

判断鼠标是否按下

* Window.drawAlpha

绘画图片到指定坐标,改变其透明度实现渐隐和渐现。

* Window.draw

绘画图片到指定坐标,可以实现闪烁(显示或不显示)

* Input.mousePosX

鼠标当前所在的X坐标

* Input.mousePosY

鼠标当前所在的Y坐标

* Image.loadToArray

加载一张图片并分割成m * n个对象后返回

 

三、总结和值得借鉴的内容

1. MenuScene和Punya的实现比较复杂,需要重点分析。

2. 学习如何用滴答数实现透明度动画、闪烁动画、砖块平移动画以及精灵动画。

3. 学习如何实现菜单按钮(选择和未选择)。