我用 GitHub 9.8k 的 Go 语言 2D 游戏引擎写了个游戏

github,8k,go,2d · 浏览次数 : 418

小编点评

**游戏引擎简介** GitHub 🌟9.8k 的 Go 语言 2D 游戏引擎名为 "ebiten引擎",它是一个兼具学习 & 娱乐的功能项目,支持跨平台运行。 **游戏设计** 该游戏使用了面向玩家的生存游戏玩法,玩家需要不断移动并避免与各种敌人碰撞,以保持游戏运行。 **开发说明** * 游戏引擎包含一个游戏窗口布局函数,用于初始化游戏窗口。 * 游戏引擎提供了一个 `Game` 结构体,用于管理游戏逻辑。 * 游戏引擎还包含了一些官方有趣的 demo,以及以我的开发为例,讲解如何使用这个引擎快速上手开发属于自己的游戏。 **游戏玩法** * 游戏玩家控制一只小狗,需要不断移动并避免与各种敌人碰撞。 * 游戏使用了面向对象的绘制技术,将游戏窗口分成左上角的渲染区域和右上角的控制区域。 * 游戏使用帧缓冲技术,以提高帧率。 **技术细节** * 游戏引擎支持跨平台运行,包括 Windows、macOS、Linux、FreeBSD、Android、IOS、Xbox、Siwtch。 * 游戏引擎支持手柄外设。 **示例代码** 游戏开发示例代码可找到在 `go-learning` 的开源仓库中: * `github.com/BaiZe1998/go-learning` **结论** ebiten引擎是一个功能丰富的 2D 游戏引擎,可用于开发各种类型的游戏项目。它是一个学习 & 娱乐的项目,值得尝试。

正文

前言

hi,大家好,这里是白泽。今天给大家分享一个 GitHub 🌟9.8k 的 Go 语言 2D 游戏引擎。

https://github.com/hajimehoshi/ebiten

引擎的贡献者依旧在积极维护,是一个兼具学习 & 娱乐的项目!

为此我也用这个引擎写了一个生存游戏: avoid-the-enemies【如下图】:https://github.com/BaiZe1998/avoid-the-enemies

当然详细的游戏设计我还是想再通过下一期文章讲解,这期的内容主要讲解游戏引擎提供的能力,一些官方有趣的 demo,以及以我的开发为例,讲解如何使用这个引擎快速上手开发属于自己的游戏。

image-20240428204456063

avoid-the-enemies 玩法

尽可能存活是你唯一要做的事!

image-20240428220026572

游戏的体验实况已经录制并上传了,欢迎你的关注 📺 B站:白泽talk,QQ群:622383022。

image-20240429092703509

🌟 当然,如果您是一位 Go 学习的新手,您可以在我开源的学习仓库:https://github.com/BaiZe1998/go-learning 中,找到我往期翻译的英文书籍,或者Go学习路线,等一系列精彩内容。

有趣的 Demo

在这个游戏引擎的 examples 目录下集成很多的游戏小 demo 以及素材,只要安装了 go 开发环境就能直接编译运行了。

而且它支持跨平台运行的:Win、macOS、Linux、FreeBSD、Android、IOS、Xbox、Siwtch 都不在话下。(支持手柄外设)

image-20240428203127172

Flappy

复刻经典 flappy bird 小游戏,只是鼠鼠实在是太大了,难度指数:5🌟。

image-20240428203725614


粒子效果

酷炫指数:5🌟。

image-20240428205602920

钢琴

娱乐指数:5🌟,午休的时候来一曲吧。

image-20240428205952526

引擎核心流程

image-20240428202143238

由于引擎本身帮助开发者完成了多平台适配,以及最重要的 UI 的渲染,因此开发游戏只需要关注左侧这张图的三个核心方法即可。

整个引擎就是一个循环,这个循环每秒大约可以执行60次,那就是达到了所谓的 FPS 60。

这个循环中要做的事有两件事,一部分写数值,一部分绘制角色。(调用上图左侧的两个 Func)。开发者需要编写 Game 结构体的 Draw 和 Update 函数,然后交由引擎每秒调用大约 60 次。

avoid-the-enemies 拆解

接下来将以我的生存小游戏为例,讲解一下这个游戏引擎的正确打开方式。

绘制游戏窗口

给定一个宽和高,就可以初始化一个游戏窗口,所有的绘制内容都将以窗口的左上角作为 (0, 0),右为x正轴,下为y正轴控制角色位置。

func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
	return screenWidth, screenHeight
}

画面绘制

下面以我编写的游戏为例,讲解一下游戏开发流程。

image-20240428213425140

以像素小人的移动来说,只要我在一秒内不断更换连续的像素图片,遍历对应的索引,并绘制连贯动作的角色图片,就能达到动画的效果了

image-20240428213509200

当然在具体的实现时,我们需要去素材网站上下载对应的图片,在并且了解对应图片的像素大小,如上图每个小人是32px*32px,因此为了达到播放跑动的效果,需要通过循环,不断获取子图,然后在一秒内快速替换。

func (g *Game) Draw(screen *ebiten.Image) {
    // ...
	// 绘制角色
    op := &ebiten.DrawImageOptions{}
    op.GeoM.Translate(g.player.x, g.player.y)
    i := (g.player.count / 5) % frameCount
    sx, sy := frameOX+i*frameWidth, frameOY
    screen.DrawImage(runnerImage.SubImage(image.Rect(sx, sy, sx+frameWidth, sy+frameHeight)).(*ebiten.Image), op)
    // ...
}

数值状态变更

假设需要实现武器每五秒钟刷新,只需要写一个武器生成器,并在 Update 方法中调用,即可得到武器的数据。再配合上述 Draw 方法,将武器渲染出来即可。

// 生成武器
func GenerateWeapon(g *Game) {
	if time.Since(g.weaponTimer) > time.Second*5 {
		g.weaponTimer = time.Now()
		if len(g.weapons) < 2 {
			g.uniqueId++
			weapon := weaponList[rand.Intn(len(weaponList))]
			switch weapon.(type) {
			case *MeleeWeapon:
				newWeapon := weapon.(*MeleeWeapon).Copy()
				// 使用指针类型有拷贝的bug,当两个人获得同一把武器的时候,旋转会draw两次,所以看起来转速快了一倍
				g.weapons[g.uniqueId] = newWeapon
				g.weaponPosition[g.uniqueId] = f64.Vec2{rand.Float64() * (screenWidth - frameWidth/2), rand.Float64() * (screenHeight - frameHeight/2)}
			case *RangedWeapon:
				newWeapon := weapon.(*RangedWeapon).Copy()
				g.weapons[g.uniqueId] = newWeapon
				g.weaponPosition[g.uniqueId] = f64.Vec2{rand.Float64() * (screenWidth - frameWidth/2), rand.Float64() * (screenHeight - frameHeight/2)}
			}
		}
	}
}

func (g *Game) Update() error {
   GenerateWeapon(g)
   return nil
}

比如需要绘制子弹的移动轨迹,可以通过一个 map 记录地图上所有子弹起始位置,目标位置,移动速度,子弹贴图等内容,通过计时器配合 Update 方法每秒多次更新子弹的数据,最后再借助 Draw 方法,完成子弹的绘制,达到子弹移动的效果。

image-20240428222012933

小节

游戏开发可能是很多人小时候的一个愿望,白泽也一样,今天实现了,很有趣很开心~

有更多好的 idea 欢迎积极评论。

与我用 GitHub 9.8k 的 Go 语言 2D 游戏引擎写了个游戏相似的内容:

我用 GitHub 9.8k 的 Go 语言 2D 游戏引擎写了个游戏

游戏引擎的贡献者依旧在积极维护,是一个兼具学习 & 娱乐的项目!为此我也用这个引擎写了一个生存游戏: avoid-the-enemies

Vue源码学习(九):响应式前置:实现对象的依赖收集(dep和watcher)

好家伙,这是目前为止最绕的一章,也是十分抽象的一章 由于实在太过抽象,我只能用一个不那么抽象的实例去说服我自己 完整代码已开源https://github.com/Fattiger4399/analytic-vue.git 1.我们要做什么? 来看这个例子, index.html setTimeou

[转帖]我所知道的线程池

https://bigbully.github.io/%E7%BA%BF%E7%A8%8B%E6%B1%A0 线程池其实或多或少都用过,不过这是我第一次阅读它的源码,包括源码附带的非常详尽的注释。发现我之前对于线程池的理解还是很浅薄的。 其实从ThreadPoolExecutor.java顶部200

一套用了 70 年的计算机架构 —— 冯·诺依曼架构

本文已收录到 GitHub · AndroidFamily,有 Android 进阶知识体系,欢迎 Star。技术和职场问题,请关注公众号 [彭旭锐] 进 Android 面试交流群。 前言 大家好,我是小彭。 上一篇文章里,我们讨论了可计算问题与图灵机的计算机模型。在理解了图灵机模型后,我们将从和

Strimzi Kafka Bridge(桥接)实战之二:生产和发送消息

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是《Strimzi Kafka Bridge(桥接)实战之》系列的第二篇,咱们直奔bridge的重点:常用接口,用实际操作体验如何用brid

穷人版生产力工具,好用得飞起 「GitHub 热点速览」

被 GPT 和 OpenAI 刷屏了一个多月,现在 GitHub Trending 已经没有什么和 gpt 无关的项目了,但是好在总有优秀的开源项目拯救我的项目疲惫。像是贴心好用的

Go版RuoYi

RuoYi-Go https://github.com/Kun-GitHub/RuoYi-Go 1. 关于我 个人介绍 2. 介绍 后端用Go写的RuoYi权限管理系统 (功能正在持续实现)后端 Gitee地址 3. 前端 RuoYi-Vue3 官方前端Vue3版 4. Go后端技术栈(持续在对齐项

Blazor开发小游戏?趁热打铁上!!!

大家好,我是沙漠尽头的狼。 网站使用Blazor重构上线一天了,用Blazor开发是真便捷,空闲时间查查gpt和github,又上线一个 [正则表达式在线验证工具](https://dotnet9.com/tools/regextester) 和几个在线小游戏,比如 [井字棋游戏](https://

Spectre.Console-实现自己的CLI

## 引言 最近发现自己喜欢用的 Todo 软件总是差点意思,毕竟每个人的习惯和工作流不太一样,我就想着自己写一个小的[Todo 项目]( https://github.com/circler3/TodoTrack ),核心的功能是自动记录 Todo 执行过程中消耗的时间(尤其面向程序员),按照自己

颠覆传统编程:用ChatGPT十倍提升生产力

我们即将见证一个新的时代!这是最好的时代,也是最坏的时代! 需求背景 背景: 平时会编写博客,并且会把这个博客上传到github上,然后自己买一个域名挂到github上。 我平时编写的博客会有一些图片来辅助说明的,写完之后如果我把图片和文字全部都上传到博客网站,后期图片很多时就会导致网站加载特别慢