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

news2024/11/26 20:42:21

前言

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

https://github.com/hajimehoshi/ebiten

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

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

当然详细的游戏设计我还是想再通过下一期文章讲解,这期的内容主要讲解游戏引擎提供的能力,一些官方有趣的 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 欢迎积极评论。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1650825.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Prompt提示词教程 | 提示工程指南 | 提示词示例 入门篇

在上一节中&#xff0c;我们介绍并给出了如何赋能大语言模型的基本示例。如果还没看而且是刚入门的同学建议看下&#xff0c;有个基本概念。 Prompt提示词教程 | 提示工程指南 | 提示工程简介https://blog.csdn.net/HRG520JN/article/details/138523705在本节中&#xff0c;我…

结合kimi chat的爬虫实战思路

背景 想钻研一下项目组件&#xff0c;找找之后的学习方向。不能自以为是&#xff0c;所以借着网开源项目网站上公布的项目内容看一下&#xff0c;那些是我可以努力去学习的&#xff08;入门的&#xff09;。首先需要获取相关内容&#xff0c;于是爬取整理。 任务1&#xff1a…

Unity与C#的关系

第一&#xff0c;我们首先需要知道Unity与C#的关系是什么&#xff1f; 第二&#xff0c;我们要明白为什么Unity会使用C#&#xff0c;而不是C&#xff1f; 第三&#xff0c;我们需要知道Unity是怎么使用C#的&#xff1f; 第一点&#xff1a; 先说结论&#xff1a;C#是Unity用…

【Verilog】big_small_cnt

通用大小计数器 timescale 1ns / 1ps // // Company: // Engineer: wengf // Create Date: // Design Name: // Module Name: big_small_cnt // Project Name: // Target Devices: // Tool Versions: // Description: // Dependencies: // Revision: // Revision 0…

一起刷C语言菜鸟教程100题(15-26含解析)

五一过的好快&#xff0c;五天假期说没就没&#xff0c;因为一些事情耽搁到现在&#xff0c;不过还是要继续学习的&#xff0c;之后就照常更新&#xff0c;先说一下&#xff0c;这个100题是菜鸟教程里面的&#xff0c;但是有一些题&#xff0c;我加入了自己的理解&#xff0c;甚…

odoo实施之创建行业demo

创建数据库&#xff0c;添加公司数据 选择应用&#xff0c;获取15天免费试用 创建完成 设置客户公司logo 创建用户 更改用户语言 前置条件&#xff1a;配置邮件 开发模式下&#xff0c;额外信息 加载demo数据

Conda下Richdem包遇到问题

Conda中Richdem包遇到问题 文章目录 Conda中Richdem包遇到问题问题一报错解决 问题二报错解决 参考 问题一 报错 RichDEM 是一套数字高程模型 &#xff08;DEM&#xff09; 水文分析工具&#xff0c;这次打算用richdem进行地形分析&#xff0c;尝试在conda里面安装richdem包的…

VMware下Ubuntu的安装教程

文章目录 一、Ubuntu如何下载1.下载官方地址https://ubuntu.com/2.点选Ubuntu服务器版本3.点击下载Ubuntu服务器版本iso镜像二、VMware安装Ubuntu服务器系统1.创建虚拟机2.选择下载好的Ubuntu服务器镜像3.创建安装完成三、Ubuntu Server如何设置1.Ubuntu Server没有中文所以全都…

windows vscode设置扩展和缓存目录

vscode的扩展和缓存占了很大的空间&#xff0c;而且默认在C盘&#xff0c;很烦。。。 修改vscode快捷方式的目标处&#xff1a;"C:\Users\Nv9\AppData\Local\Programs\Microsoft VS Code\Code.exe" --extensions-dir "D:\Program Cache\VScode\extensions"…

sql注入练习

1.什么是SQL注入 SQL注入是比较常见的网络攻击方式之一&#xff0c;它不是利用操作系统的BUG来实现攻击&#xff0c;而是针对程序员编写时的疏忽&#xff0c;通过SQL语句&#xff0c;实现无账号登录&#xff0c;甚至篡改数据库 2.sql注入原理 攻击者注入一段包含注释符的SQL语…

kraken2 最新版安装,极简模式

kraken2 git clone https://github.com/DerrickWood/kraken2.gitcd kraken2./install_kraken2.sh /opt/krakenvim .bashrc ---------------- # Kraken export PATH"/opt/kraken:$PATH" ----------------source .bashrc Note: 不晓得是不是我设置了清华源&#xff0c…

Spring Boot集成Swagger快速入门Demo

1.什么是Swagger&#xff1f; Swagger 是一个规范和完整的框架&#xff0c;用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。 主要作用&#xff1a; 使得前后端分离开发更加方便&#xff0c;有利于团队协作。&#xff08;实际开发中&#xff0c;接口文档的内容会不停的…

kafka学习笔记(三、生产者Producer使用及配置参数)

1.简介 1.1.producer介绍 生产者就是负责向kafka发送消息的应用程序。消息在通过send()方法发往broker的过程中&#xff0c;有可能需要经过拦截器(Interceptor)、序列化器(Serializer)和分区器(Partitioner)的一系列作用后才能被真正的发往broker。 demo: public class Kafk…

【NodeMCU实时天气时钟温湿度项目 4】通过NTPClient库获取实时网络时间并显示在TFT屏幕上

今天是【实时天气时钟温湿度项目】第四专题&#xff0c;主要内容是&#xff1a;学习导入NTPClient库&#xff0c;通过这个库获取实时网络时间&#xff0c;显示在1.3寸TFT液晶屏幕上。此前三个专题&#xff0c;请选择查看以下链接。 第一专题内容&#xff0c;请参考 【N…

使用Docker安装MySQL5.7.36

拉取镜像并查看 docker pull mysql:5.7.36拉取成功后查看&#xff08;非必须&#xff09; docker images创建并设置宿主机 mysql 配置文件目录和数据文件目录 创建相关文件夹将容器中的mysql数据保存到本地&#xff0c;这样即使容器被删除&#xff0c;数据也不会丢失。 mkd…

牛客NC142 最长重复子串【中等 字符串 Java/Go】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/4fe306a84f084c249e4afad5edf889cc 思路 注意&#xff1a;题目给的时间复杂度是O(N^2)那么直接套用双重循环&#xff1a;外层循环i为假定起始重复子串的初始位置&#xff0c;内层循环的j为假定重复子串的结束位置…

每日一题5:Pandas-修改列

一、每日一题 一家公司决定增加员工的薪水。 编写一个解决方案&#xff0c;将每个员工的薪水乘以2来 修改 salary 列。 返回结果格式如下示例所示。 解答&#xff1a; import pandas as pddef modifySalaryColumn(employees: pd.DataFrame) -> pd.DataFrame:employees.loc[…

人工神经网络初步

大家好&#xff0c;这里是七七&#xff0c;由于各种比赛的缘故&#xff0c;使用了很多人工神经网络模型。但是很多的原理都不是很明白&#xff0c;就导致了不能灵活地运用┭┮﹏┭┮。为此&#xff0c;去看了些人工神经网络原理书&#xff0c;写下此专题。 在进入正文之前要先…

Delta lake with Java--数据增删改查

之前写的关于spark sql 操作delta lake表的&#xff0c;总觉得有点混乱&#xff0c;今天用Java结合真实的数据来进行一次数据的CRUD操作&#xff0c;所涉及的数据来源于Delta lake up and running配套的 GitGitHub - benniehaelen/delta-lake-up-and-running: Companion reposi…

Mac idea gradle解决异常: SSL peer shut down incorrectly

系统&#xff1a;mac 软件&#xff1a;idea 解决异常: SSL peer shut down incorrectly 查看有没有安装 gradle -v安装 根据项目gradle提示安装版本 brew install gradle7idea的配置 在settings搜索gradle&#xff0c;配置Local installation&#xff0c;选择自己的安装目录…