termloop, 在Termbox平台上,构建了基于终端的游戏引擎

分享于 

12分钟阅读

GitHub

  繁體 雙語
Terminal-based game engine for Go, built on top of Termbox
  • 源代码名称:termloop
  • 源代码网址:http://www.github.com/JoelOtter/termloop
  • termloop源代码文档
  • termloop源代码下载
  • Git URL:
    git://www.github.com/JoelOtter/termloop.git
    Git Clone代码到本地:
    git clone http://www.github.com/JoelOtter/termloop
    Subversion代码到本地:
    $ svn co --depth empty http://www.github.com/JoelOtter/termloop
    Checked out revision 1.
    $ cd repo
    $ svn up trunk
    

    Termloop

    Join the chat at https://gitter.im/JoelOtter/termloopGoDoc

    Termloop是一款纯围棋游戏引擎,建立在优秀的 Termbox游戏之上。 它为在终端构建游戏提供了简单的渲染循环,并且专注于使终端游戏开发尽可能简单和有趣。

    Termloop仍处于活动状态,因此更改可能会中断。 如果我希望在这个阶段有任何重大的改变,我希望这个阶段不太多。 请求请求和问题非常简单,欢迎使用,并且确实可以随时询问你在Gitter上可能遇到的问题。 我希望你喜欢用 Termloop,我已经a 了。

    安装

    安装和更新 go get -u github.com/JoelOtter/termloop

    特性

    • 键盘和鼠标输入
    • 碰撞检测
    • 渲染计时器
    • 用于模拟'相机'运动的标高偏移
    • 调试日志
    • 内置的实体类型,例如:
    • 帧速率计数器
    • 矩形
    • 文本
    • 从ASCII艺术加载实体
    • 从图像加载彩色贴图
    • 从JSON加载级别映射
    • 可选'像素模式'- 向终端字符绘制两个'象素',使屏幕高度增加,以便能够呈现文本。
    • 纯围棋- 轻松移植游戏,交叉编译构建正确。

    首先,查看路线图上的内容,看一下问题跟踪器( )。

    termloop/额外

    Termloop附加是类型和函数的集合,它的使用不会导致完全可以移植的二进制文件。 但是,如果你愿意在项目中需要这些依赖项,那么它们应该与Termloop的其余部分非常好地集成。 其中的一些示例使用这些附加项。

    • 音频播放
    • audio.go
    • 要求:PortAudio和 libsndfile

    用Termloop构建的

    你可以随意添加你的请求请求 !

    教程

    更完整的文档将很快添加到维基。 同时,查看本教程。GoDoc插件或者包括示例的 如果你在本教程中遇到了问题,请不要担心,完整的源代码是

    创建一个空白Termloop游戏就像下面这样简单:

    package mainimport tl "github.com/JoelOtter/termloop"funcmain() {
     game:= tl.NewGame()
     game.Start()
    }

    我们可以按Ctrl+C键退出。 只是一个空白屏幕- 让我们更有趣一点。

    让我们做一个绿色的背景,因为草是非常好的跑步。 我们创建了一个新的级别,如下所示:

    level:= tl.NewBaseLevel(tl.Cell{
     Bg: tl.ColorGreen,
     Fg: tl.ColorBlack,
     Ch: 'v',
    })

    单元格是表示终端上一个单元格的结构。 我们可以设置它的背景和前景色,以及显示的字符。 用这种方式创建一个 BaseLevel 以这个单元填充这个级别。

    让我们做一个漂亮的湖。 我们将使用 rectangle。 我们将把湖置于( 10,10 ) 位置,宽度为 50和高度 20. 所有测量均以终端字符 ! 最后一个参数是 rectangle的颜色。

    level.AddEntity(tl.NewRectangle(10, 10, 50, 20, tl.ColorBlue))

    我们不需要使用一个级别,我们可以直接将实体添加到屏幕中。 ! 这对于构建HUD非常有用,或者非常简单的应用程序。 但是,如果我们想要相机滚动或者碰撞检测,我们将需要使用一个级别。

    把我们目前拥有的东西组合在一起:

    package mainimport tl "github.com/JoelOtter/termloop"funcmain() {
     game:= tl.NewGame()
     level:= tl.NewBaseLevel(tl.Cell{
     Bg: tl.ColorGreen,
     Fg: tl.ColorBlack,
     Ch: 'v',
     })
     level.AddEntity(tl.NewRectangle(10, 10, 50, 20, tl.ColorBlue))
     game.Screen().SetLevel(level)
     game.Start()
    }

    当我们用 go run tutorial.go 运行它时,它看起来像这样:

    很好我们来创建一个可以围绕环境漫游的角色。 这里我们将使用对象组合- 我们将创建一个新的结构类型,它扩展了一个实体。

    为了让Termloop绘制新类型,我们需要实现 Drawable 接口,这意味着我们需要两种方法: 英镑 Draw() 和英镑 Tick()。 Draw方法定义如何将我们的类型绘制到屏幕内部,而Tick方法定义如何处理输入。

    我们不需要为 Draw 做任何特殊操作,它已经由 Entity 处理,所以我们只需要一个 Tick:

    typePlayerstruct {
     *tl.Entity}func(player *Player) Tick(eventtl.Event) {
     if event.Type == tl.EventKey { // Is it a keyboard event?x, y:= player.Position()
     switch event.Key { // If so, switch on the pressed key.case tl.KeyArrowRight:
     player.SetPosition(x+1, y)
     case tl.KeyArrowLeft:
     player.SetPosition(x-1, y)
     case tl.KeyArrowUp:
     player.SetPosition(x, y-1)
     case tl.KeyArrowDown:
     player.SetPosition(x, y+1)
     }
     }
    }

    现在我们已经建立了玩家类型,让我们在级别上添加一个。

    player:=Player{tl.NewEntity(1, 1, 1, 1)}// Set the character at position (0, 0) on the entity.player.SetCell(0, 0, &tl.Cell{Fg: tl.ColorRed, Ch: ''})
    level.AddEntity(&player)

    再次运行游戏,我们看到我们现在可以使用箭头键在地图上移动。 Neato 我们可以像草草一样轻松地跨越湖。 我们的角色不是 Messiah,他是一个非常淘气的男孩,所以让我们加入一些冲突。

    在Termloop中,我们有两个用于碰撞的接口。 给您。

    // Physical represents something that can collide with another// Physical, but cannot process its own collisions.// Optional addition to Drawable.typePhysicalinterface {
     Position() (int, int) // Return position, x and ySize() (int, int) // Return width and height}// DynamicPhysical represents something that can process its own collisions.// Implementing this is an optional addition to Drawable.typeDynamicPhysicalinterface {
     Position() (int, int) // Return position, x and ySize() (int, int) // Return width and heightCollide(Physical) // Handle collisions with another Physical}

    这很简单- 如果我们希望我们的对象是'实心',那么我们就实现物理。 如果我们想要一个实体对象来实际处理它自己的冲突,我们就实现了 DynamicPhysical ! 基本上这只是在你的类型中增加一个方法。

    注意,因为性能原因,你应该尽可以能少的DynamicPhysicals,例如,我们的玩家将是一个物理。

    rectangle 类型已经实现物理,所以我们实际上不需要做任何事情。 让我们继续为玩家添加我们的方法。 我们必须修改结构和刻度方法,以便跟踪以前的玩家位置,如果它碰撞了。

    typePlayerstruct {
     *tl.Entity prevX int prevY int}func(player *Player) Tick(eventtl.Event) {
     if event.Type == tl.EventKey { // Is it a keyboard event? player.prevX, player.prevY = player.Position()
     switch event.Key { // If so, switch on the pressed key.case tl.KeyArrowRight:
     player.SetPosition(player.prevX+1, player.prevY)
     case tl.KeyArrowLeft:
     player.SetPosition(player.prevX-1, player.prevY)
     case tl.KeyArrowUp:
     player.SetPosition(player.prevX, player.prevY-1)
     case tl.KeyArrowDown:
     player.SetPosition(player.prevX, player.prevY+1)
     }
     }
    }func(player *Player) Size() (int, int) {
     return player.Size()
    }func(player *Player) Position() (int, int) {
     return player.Position()
    }func(player *Player) Collide(collisiontl.Physical) {
     // Check if it's a Rectangle we're colliding withif_, ok:= collision.(*tl.Rectangle); ok {
     player.SetPosition(player.prevX, player.prevY)
     }
    }

    没有太多的额外代码 ! 现在我们可以看到玩家不能从lake出来。 如果你看到播放器稍微重叠在一边,那很可以能是因为我们使用的'stick'字符不是标准的宽度。

    我们现在得到的东西看起来有点像一个简单的探索游戏。 还有一件事要添加- 让我们把摄像机滚动到屏幕中心。

    Termloop中没有'相机',就像你在其他图形库中可能会发现的那样。 相反,我们设置了一个偏移,屏幕适当地绘制了我们的水平。 在我们的例子中,我们需要的只是让玩家有一个指向级别的指针,因这里我们可以调用。 然后,我们简单地修改绘图方法,如下所示:

    typePlayerstruct {
     *tl.Entity prevX int prevY int level *tl.BaseLevel}func(player *Player) Draw(screen *tl.Screen) {
     screenWidth, screenHeight:= screen.Size()
     x, y:= player.Position()
     player.level.SetOffset(screenWidth/2-x, screenHeight/2-y)
     // We need to make sure and call Draw on the underlying Entity. player.Entity.Draw(screen)
    }// in func mainplayer:=Player{
     Entity: tl.NewEntity(1, 1, 1, 1),
     level: level,
    }

    就是这样了我们现在应该看到摄像机。 当然,由于 static,重复背景,这看起来不太令人满意- 看起来像玩家站在一起。 我们可以修补这个问题,例如,只要在播放机接近屏幕边缘时更新偏移量。 我将把它留给你作为一个挑战。

    我们已经达到了教程的结尾- 我希望它是有用的 ! 如果你想进一步了解 Termloop,Wiki上会提供更全面的文档。 同时,你可以查看 GoDoc插件,也可以查看包含的示例示例。 我也会在 Gitter上闲逛如果你有任何问题的话。 ,请给我看看你是否 make !


    BASE  GAM  TERM  终端  游戏引擎  
    相关文章