"If you program and want any longevity to your work, make a game.
All else recycles, but people rewrite architectures to keep games alive.", _why

如果想让你的代码长寿 ,那就做一个游戏。

所有其他的代码都在回收站了,但是人们总会花时间更新代码让游戏还活着。

----- _why

gosu的安装(ubuntu环境)

sudo apt-get install build-essential freeglut3-dev libfreeimage-dev libgl1-mesa-dev libopenal-dev libpango1.0-dev libsdl-mixer1.2-dev libsdl-ttf2.0-dev libsndfile-dev libxinerama-dev
sudo gem install gosu 

gosu的用法

1 覆写window的回调

创建一个完整的Gosu应用,最简单的写法是写一个Gosu::Window的子类,下面是一个最小的GameWindow类写法:
require 'gosu'class GameWindow < Gosu::Windowdef initializesuper 640, 480, falseself.caption = "Gosu Tutorial Game"enddef updateenddef drawend
endwindow = GameWindow.new
window.show

以上代码初始化了 Gosu::Window基类,创建了640x480的窗口,改变了窗口的标题。

update() 和 draw() 覆写了Gosu::Window的两个成员方法。
update()缺省下每秒调用60次,包含了主游戏逻辑:移动对象,碰撞等等
随后调用的draw()用于重绘,如果FPS(每秒帧数)过低则跳过。重绘包括整个屏幕和所有无逻辑代码
再往下,一个window对象被创建,调用其show方法,如果不关闭窗口,不会有返回值
现在,你拥有了一个小黑window和一个自定义的title!
更详细的方法描述
  • draw是十分灵活的。通常的流程如上图所示,但是draw通常在系统想要重绘widnow的时候才被调用,它可能发生在直接调用show方法时,或调用两次update方法之间,或在window被一个frame遮挡时。
  • 由此可见,你无法知道哪一个回调被首先调用,initialize必须建立一个有效的状态,如果update中包含if player == nil then respawn(),那么initialize应该包含respawn()你可以在初始化时把update()作为最后一个调用。
  • 由于draw如此的灵活,它只渲染当前状态而不改变任何东西,包括动画,如果你用draw实现一个功能,用 read-only模式也许更安全。
  • 在update中,你可能想要用button_down?察看一个按钮的状态,因为在button_down?update前,输入事件应该被触发,它必须在update前发生,遗憾的是你无法直接用draw直接反应这一最新的按钮事件;一个update调用将在中间发生。
  • 因为TextInput可以回调到游戏中,所以它不是一个缓存并且能发生在循环的任意位置,你不能指望text()在update和draw中是相同的。
  • 但不要害怕,Gosu不是多线程的,没有一个回调是可以被打断的

2 图片应用

class GameWindow < Gosu::Windowdef initializesuper(640, 480, false)self.caption = "Gosu Tutorial Game"@background_image = Gosu::Image.new(self, "media/Space.png", true)enddef updateenddef draw@background_image.draw(0, 0, 0)end
end

Gosu::Image#initialize有三个参数,第一个:绑定的窗口(self),所有的gosu资源初始化都需要一个内部引用的窗口;第二个:给定的图片文件名。第三个:是否创建粗边框,具体见基本概念的解释。

window的draw()成员方法是画图的地方,所以在这里绘制我们的背景图。
参数配置很明显,从(0,0)开始,第三个参数是z轴,详见 基本概念。
2.1 人物与移动
简单人物类
class Playerdef initialize(window)@image = Gosu::Image.new(window, "media/Starfighter.bmp", false)@x = @y = @vel_x = @vel_y = @angle = 0.0@score = 0enddef warp(x, y)@x, @y = x, yenddef turn_left@angle -= 4.5enddef turn_right@angle += 4.5enddef accelerate@vel_x += Gosu::offset_x(@angle, 0.5)@vel_y += Gosu::offset_y(@angle, 0.5)enddef move@x += @vel_x@y += @vel_y@x %= 640
    @y %= 480@vel_x *= 0.95@vel_y *= 0.95enddef draw@image.draw_rot(@x, @y, 1, @angle)end
end

有几件事情要说明:

  • Player#accelerate 用了offset_x/offset_y方法,它们类似于sin/cos,比如:如果一个东西沿30度角移动100像素,它其实是通过水平移动offset_x(30, 100) pixels 和垂直移动offset_y(30, 100) pixels 得到的
  • 当加载pmp文件时,gosu将会把0xff00ff(樱红色/品红;非常丑陋的一种粉红色)变为透明色
  • 注意:draw_rot将把图片中心放到(x,y)上-不是左上角。可以通过center_x/center_y 参数控制
  • draw的所有方法和参数详见这里
2.2 整合以上代码
class GameWindow < Gosu::Windowdef initializesuper(640, 480, false)self.caption = "Gosu Tutorial Game"@background_image = Gosu::Image.new(self, "media/Space.png", true)@player = Player.new(self)@player.warp(320, 240)enddef updateif button_down? Gosu::KbLeft or button_down? Gosu::GpLeft then@player.turn_leftendif button_down? Gosu::KbRight or button_down? Gosu::GpRight then@player.turn_rightendif button_down? Gosu::KbUp or button_down? Gosu::GpButton0 then@player.accelerateend@player.moveenddef draw@player.draw@background_image.draw(0, 0, 0);enddef button_down(id)if id == Gosu::KbEscapecloseendend
end

嗯 可以看到 gosu::window提供了两个方法 button_down(id)  和  button_up(id)以供覆盖,缺省下什么都不做。按esc推出窗口,预设的button列表参看rdoc。当按下按钮时,update()方法将开始运作,调用人物行动方法。

3. 简单动画

首先,我们通过替换下列常量来去掉z轴排列
module ZOrderBackground, Stars, Player, UI = *0..3
end

什么是动画?一组序列的图片。因此我们用一个ruby数组存储他们,在真实游戏中,不可能出现一些满足个人需求的类,但是我们这里为了教学方便简易做一个

让我们做一个动画星星的动画,星星会随机生成在屏幕上知道我们收集它们,星星类的定义十分简单
class Starattr_reader :x, :ydef initialize(animation)@animation = animation@color = Gosu::Color.new(0xff000000)@color.red = rand(256 - 40) + 40@color.green = rand(256 - 40) + 40@color.blue = rand(256 - 40) + 40@x = rand * 640@y = rand * 480enddef draw  img = @animation[Gosu::milliseconds / 100 % @animation.size];img.draw(@x - img.width / 2.0, @y - img.height / 2.0,ZOrder::Stars, 1, 1, @color, :add)end
end

因为我们不想每一个星星重复加载动画,我们不能再构造函数中做这个,但是可以通过它从其他地方入手(window分三段加载动画)

每一百毫秒展示星星动画的不同的帧,img是由 Gosu::milliseconds  返回的时间被100所除,再模上帧数,这个img是一个在星星中心点的,以构造函数中的随机颜色为参数的叠加绘图
现在在play中实现收集星星的工作
class Player...def score@scoreenddef collect_stars(stars)if stars.reject! {|star| Gosu::distance(@x, @y, star.x, star.y) < 35 } then@score += 1endend
end

添加新代码

class Window < Gosu::Windowdef initializesuper(640, 480, false)self.caption = "Gosu Tutorial Game"@background_image = Gosu::Image.new(self, "media/Space.png", true)@player = Player.new(self)@player.warp(320, 240)@star_anim = Gosu::Image::load_tiles(self, "media/Star.png", 25, 25, false)@stars = Array.newenddef update...@player.move@player.collect_stars(@stars)if rand(100) < 4 and @stars.size < 25 then@stars.push(Star.new(@star_anim))endenddef draw@background_image.draw(0, 0, ZOrder::Background)@player.draw@stars.each { |star| star.draw }end...

完成了!你可以收集星星了~

4. 文字与声音

最后,我们想画当前分数使用位图字体,每次玩家收集一个星星发出“哔哔”声。窗口将处理的文本部分,加载字体20像素高:
class Window < Gosu::Windowdef initialize...@font = Gosu::Font.new(self, Gosu::default_font_name, 20)end...def draw@background_image.draw(0, 0, ZOrder::Background)@player.draw@stars.each { |star| star.draw }@font.draw("Score: #{@player.score}", 10, 10, ZOrder::UI, 1.0, 1.0, 0xffffff00)end
end

分数留给玩家

class Playerattr_reader :scoredef initialize(window)@image = Gosu::Image.new(window, "media/Starfighter.bmp", false)@beep = Gosu::Sample.new(window, "media/Beep.wav")@x = @y = @vel_x = @vel_y = @angle = 0.0@score = 0end...def collect_stars(stars)stars.reject! do |star|if Gosu::distance(@x, @y, star.x, star.y) < 35 then@score += 10@beep.playtrueelsefalseendendend
end
这个游戏就到这里了~

这就是gosu!一切取决于你的想象力。

如果你想得知gosu究竟能做到什么地步,看一看在Gosu例子展示板。

ruby游戏框架:gosu与chingu(一)相关推荐

  1. ruby游戏框架:gosu与chingu(二)

    Chingu - OpenGL accelerated 2D Game framework in Ruby chingu核心方法 Chingu包括以下核心类/概念: Chingu::Window 主窗 ...

  2. ruby游戏框架:gosu与chingu(基本概念)

    Z Ordering 在gosu中,所有的绘图操作接受一个叫做"z"的浮点值(技术上讲,一个double值).z数高的在z数低的上面,如果两个东西有相同的z值,他们的顺序应为方法调 ...

  3. 【CSON原创】HTML5游戏框架cnGameJS开发实录(外部输入模块篇)

    返回目录 1.为什么我们需要外部输入模块? 在游戏中我们常常用到类似这样的操作:鼠标点击某位置,玩家对象移动到该位置,或者按鼠标方向键,玩家向不同方向移动,等等.这些操作无一不用与外部输入设备打交道. ...

  4. 基础知识漫谈(3) 组合基础知识,设计游戏框架

    如何让画面动起来? 都知道动画的原理,想想看跑马灯,在任意时刻把跑马灯按停,面对眼睛的那附图,它叫做帧(Frame). 帧,就是一串儿连贯动画里的单个截面. 玩儿游戏的人知道,要达到基本流畅的水准,3 ...

  5. swift语言注册非免费苹果账号iOS游戏框架Sprite Kit基础教程

    swift语言注册非免费苹果账号iOS游戏框架Sprite Kit基础教程 1.2.3  注册非免费苹果账号swift语言注册非免费苹果账号iOS游戏框架Sprite Kit基础教程 免费的苹果账号在 ...

  6. Swift版iOS游戏框架Sprite Kit基础教程下册

    Swift版iOS游戏框架Sprite Kit基础教程下册 试读下载地址:http://pan.baidu.com/s/1qWBdV0C  介绍:本教程是国内唯一的Swift版的Spritekit教程 ...

  7. iOS游戏框架Sprite Kit基础教程第1章编写第一个Sprite Kit程序

    iOS游戏框架Sprite Kit基础教程第1章编写第一个Sprite Kit程序 程序是为了实现特定目标或解决特定问题而用计算机语言编写的命令序列的集合.本章将以编写第一个Sprite Kit程序为 ...

  8. iOS游戏框架Sprite Kit基础教程——Swift版上册

    iOS游戏框架Sprite Kit基础教程--Swift版上册 试读下载地址:http://pan.baidu.com/s/1qWBdV0C  介绍:本教程是国内唯一的Swift版的Spritekit ...

  9. Unity 游戏框架搭建 (二十一) 使用对象池时的一些细节

    上篇文章使用SafeObjectPool实现了一个简单的Msg类.代码如下: class Msg : IPoolAble,IPoolType{#region IPoolAble 实现public vo ...

最新文章

  1. 要成为一个成熟的软件工程师不容易啊
  2. Linux时间子系统之三:时间的维护者:timekeeper
  3. Lighttpd日志打印格式
  4. SGU 201 Non Absorbing DFA (DP)
  5. C#使用Windows Service
  6. TeamViewer 远程设备的画面黑屏怎么办?
  7. 【C/C++】Socket编程实例解析
  8. STM32 学习周记
  9. java 切图 软件_Java 切图
  10. linux种子搜索关键字,基于 DHT 网络的磁力链接和BT种子的搜索引擎架构
  11. 关于支付宝口碑的界面问题
  12. Windows+Nvdia显卡配置Tensorflow
  13. win10电脑任务栏软件图标变成白色解决办法
  14. CF1282 B 背包
  15. 批量删除 Word、PPT 和 PDF 文件的第一页或某个特定页
  16. 如何加声调口诀_拼音标声调的口诀歌
  17. 让我们用 Node.js 写自己的 DDNS 动态域名程序
  18. oeasy教您玩转vim - 21 - 状态横条
  19. 嵌入式产品如何支持阿拉伯文显示---看这一篇就够了
  20. php类中遍历中的rewind方法,PHP rewind( )用法及代码示例

热门文章

  1. QGIS查看属性和选择要素
  2. 飞秋 公司在发展过程中
  3. 服务器文件夹重定向,使用组策略将用户文件夹重定向到D盘
  4. 有人分析过微信和张小龙没?
  5. python@jit
  6. 【汤鸿鑫 3D太极】5年目标规划(基本功、套路、实战搏击)
  7. 简单理解光会产生折射的原因及折射定律的推导
  8. oracle电子商务套件ebs,Oracle电子商务套件EBS(E-Business Suite)研发战略和路线图.ppt...
  9. 闲鱼python_自动化篇 | 你想要的闲鱼日常操作,Python 给你实现了
  10. 开企业邮箱需要服务器么,企业邮箱一定要虚拟主机吗